优化实体框架查询以进行导入

时间:2016-07-20 09:01:25

标签: c# entity-framework-6

因为我从具有上下文Bar的数据库导入数据到具有MICSYDBCONTEXT的数据库。

由于BRIA_REALDBCONTEXT数据库中有280'000条记录,我发现导入10000条记录需要5个小时,因此我迫切需要对查询进行某种优化。我正在使用Entity Framework 6,作为初级开发人员,我将不胜感激。

MICSYDBCONTEXT

1 个答案:

答案 0 :(得分:1)

这个问题很常见,

我们可以将其分为三类:

  • 添加与AddRange性能
  • 阅读&数据库往返
  • 写作&数据库往返

添加与AddRange效果

每次添加新记录时Add方法都会尝试检测更改,而AddRange只执行一次。每次检测更改可能需要几分钟。

这个问题很容易解决,只需创建两个列表,将实体添加到此列表中,并在末尾使用AddRange和列表。

var DLV_DOC_STEPS = new List<DLV_DOC_STEP>();
var DLV_DOCS = new List<DLV_DOC>();

foreach(...)
{
    foreach(...)
    {
        DLV_DOC_STEPS.Add(DLVSTEP);
    }

    DLV_DOCS.Add(DOC);
}

context2.DLV_DOC_STEP.AddRange(DLV_DOC_STEPS);
context2.DLV_DOC.AddRange(DLV_DOC);
context2.SaveChanges

另一种解决方案是在开始时禁用AutoDetectChange&amp;&amp;在SaveChanges之前重新启用它。我推荐第一个解决方案,但两者都有效。

ctx.Configuration.AutoDetectChangesEnabled = false;
foreach(var item in Doc)
{
    // ...code...
}

ctx.Configuration.AutoDetectChangesEnabled = true;
ctx.SaveChanges();

阅读&amp;数据库往返

应用程序正在执行太多的数据库往返

您多次在以下实体中进行查询:

  • DEFDOCTYPE
  • DLV_SSERVICE
  • UCM_PERSON
  • DOCMOVE

您执行数以百万计的数据库往返是疯狂的,因此您的应用程序当然非常慢!

解决方案

  • 尝试先加载所有数据,然后使用字典从内存中获取实体(如果表格中没有太多记录)。

示例:

var defDoctTypeDict = context.DEFDOCTYPE.AsNoTracking().ToList().ToDictionary(x => x.ID);

foreach(var item in Doc)
{
    DEFDOCTYPE micsysserviceName;

    defDoctTypeDict.TryGetValue(item.DOCTYPE, out micsysserviceName);
    if(micsysserviceName != null)
    {
        // ...code...
    }

    // ...code...
}

写作&amp;数据库往返

每次保存记录时,都会执行数据库往返。

免责声明:我是该项目的所有者Entity Framework Extensions

此库允许执行:

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

您可以在批处理结束时调用BulkSaveChanges,也可以创建一个列表以直接插入和使用BulkInsert,以获得更高的性能。

BulkSaveChanges解决方案(比SaveChanges更快)

context2.DLV_DOC_STEP.AddRange(DLV_DOC_STEPS);
context2.DLV_DOC.AddRange(DLV_DOC);
context2.BulkSaveChanges

BulkInsert解决方案(最快速度超过BulkSaveChanges但不保存相关实体)

context2.BulkInsert(DLV_DOC_STEPS);
context2.BulkInsert(DLV_DOC);