创建大量对象时内存不足C#

Bas*_*Bas 15 c# memory object out-of-memory linq-to-sql

我正在处理我的应用程序中的100万条记录,这是从MySQL数据库中检索的.为此,我使用Linq获取记录并使用.Skip()和.Take()一次处理250条记录.对于每个检索到的记录,我需要创建0到4个项目,然后将其添加到数据库中.因此,必须创建的项目总数平均约为200万.

IQueryable<Object> objectCollection = dataContext.Repository<Object>();
int amountToSkip = 0;
IList<Object> objects = objectCollection.Skip(amountToSkip).Take(250).ToList();
while (objects.Count != 0)
        {
            using (dataContext = new LinqToSqlContext(new DataContext()))
            {
                foreach (Object objectRecord in objects)
                {
                    // Create 0 - 4 Random Items
                    for (int i = 0; i < Random.Next(0, 4); i++)
                    {
                        Item item = new Item();
                        item.Id = Guid.NewGuid();
                        item.Object = objectRecord.Id;
                        item.Created = DateTime.Now;
                        item.Changed = DateTime.Now;
                        dataContext.InsertOnSubmit(item);
                    }
                }
                dataContext.SubmitChanges();
            }
            amountToSkip += 250;
            objects = objectCollection.Skip(amountToSkip).Take(250).ToList();
        }
Run Code Online (Sandbox Code Playgroud)

现在,在创建Items时出现问题.运行应用程序(甚至不使用dataContext)时,内存会持续增加.这就像物品永远不会被处理掉.有没有人注意到我做错了什么?

提前致谢!

Bas*_*Bas 7

好吧,我刚刚与我的一位同事讨论过这种情况,我们已经找到了以下可行的解决方案!

int amountToSkip = 0;
var finished = false;
while (!finished)
{
      using (var dataContext = new LinqToSqlContext(new DataContext()))
      {
           var objects = dataContext.Repository<Object>().Skip(amountToSkip).Take(250).ToList();
           if (objects.Count == 0)
                finished = true;
           else
           {
                foreach (Object object in objects)
                {
                    // Create 0 - 4 Random Items
                    for (int i = 0; i < Random.Next(0, 4); i++)
                    {
                        Item item = new Item();
                        item.Id = Guid.NewGuid();
                        item.Object = object.Id;
                        item.Created = DateTime.Now;
                        item.Changed = DateTime.Now;
                        dataContext.InsertOnSubmit(item);
                     }
                 }
                 dataContext.SubmitChanges();
            }
            // Cumulate amountToSkip with processAmount so we don't go over the same Items again
            amountToSkip += processAmount;
        }
}
Run Code Online (Sandbox Code Playgroud)

通过这个实现,我们每次都配置Skip()和Take()缓存,因此不会泄漏内存!


All*_*nek 5

啊,好旧的InsertOnSubmit内存泄漏.当我尝试使用LINQ to SQL从大型CVS文件加载数据时,我遇到过这种情况并且多次撞到墙上.问题是即使在调用之后SubmitChanges,DataContext仍继续跟踪已添加的所有对象InsertOnSubmit.解决方案是SubmitChanges在一定数量的对象之后,然后DataContext为下一批创建一个新对象.当旧DataContext的垃圾被收集时,所有被它跟踪的插入对象(以及你不再需要的)也是如此.

"可是等等!" 你说,"创建和处理许多DataContext会产生巨大的开销!".好吧,如果您创建单个数据库连接并将其传递给每个DataContext构造函数,那就不是了.这样,始终保持与数据库的单个连接,并且该DataContext对象是一个轻量级对象,表示一个小工作单元,应在完成后丢弃(在您的示例中,提交一定数量的记录).