【问题标题】:Saving through Entity Frameworks taking too much time通过实体框架保存需要太多时间
【发布时间】:2014-02-04 10:02:42
【问题描述】:

我正在使用 Entity Frameworks 6.0.2 将 Observable 集合中的记录保存到表中,下面是代码

   foreach(var item in obcollection)
   { 
       cid=InsertClaimsInfoes;
   }


    private long InsertClaimsInfoes()
    {
            using (OptimusEntities opt = new OptimusEntities())
            {
                var x = cc.Provider.Split(',')[1];
                var patf = cc.PatientName.Split(',')[1];
                var patl = cc.PatientName.Split(',')[0];
                var z = opt.Providers.Where(i => i.ProviderFirstName.ToLower().Trim() == x.ToLower().Trim()).FirstOrDefault().Id;


                ClaimsInfo _claimInfo = new ClaimsInfo();
                {
                    _claimInfo.Id = Convert.ToInt64(opt.ClaimsInfoes.Max(i => i.Id) + 1);
                    _claimInfo.BatchID = 1;
                    _claimInfo.ClientID = 122;
                    _claimInfo.PayorID = 0;

                    _claimInfo.ReceiverProviderId = opt.Providers.Where(i => 
                i.ProviderFirstName.ToLower().Trim() == x.ToLower().Trim()).FirstOrDefault().Id;

                    _claimInfo.ServiceProviderId = _claimInfo.ReceiverProviderId;
                    _claimInfo.SubscriberId = _claimInfo.ReceiverProviderId;

                    _claimInfo.PatientId = opt.Patients.Any(i => i.FirstName.ToLower().Trim() == patf.ToLower().Trim()) ? opt.Patients.Where(j => 
                j.FirstName.ToLower().Trim() == patf.ToLower().Trim()).FirstOrDefault().Id : InsertPatient(patf, patl, cc.DOB, 122, cc.Insurance);

                    _claimInfo.InsuranceName = cc.CarrierName;
                    _claimInfo.SelfClaim = true;
                    _claimInfo.DOSFrom = Convert.ToDateTime(cc.DOS);
                    _claimInfo.DOSTo = Convert.ToDateTime(cc.DOE);
                    _claimInfo.BillingDate = Convert.ToDateTime(cc.DOE);
                    _claimInfo.ClaimNum = cc.Insurance;
                    _claimInfo.SubmitAmount = Convert.ToDecimal(cc.BillValue);
                }
                //opt.Configuration.ProxyCreationEnabled = false;
                opt.ClaimsInfoes.Add(_claimInfo);

                opt.SaveChanges();

                return _claimInfo.Id;

        }

    }

保存记录需要 4-5 秒。 ObservableCollection 的大小超过 1000。保存所有 Observable Collection 大约需要 30 分钟。我在这里做错了什么需要更多时间。我可以做些什么来提高性能。

【问题讨论】:

  • 对于每个新项目,您对数据库进行超过 2 次查询,效率不高。使用缓存。当处理了大约 100 个元素而不是一个元素时,如何调用 SaveChanges
  • Disable change tracking, save in smaller batches, recreate context 或(也许最重要的是)不要使用 EF 进行批量插入,而是更喜欢 SqlBulkCopy... :) 在每个新条目上,您至少要进行 2 次数据库访问,这将是昂贵的。
  • 谢谢..我试试看,让你知道性能的变化

标签: c# .net entity-framework entity-framework-6


【解决方案1】:

您正在创建一个到数据库的新连接每条记录并单独保存每条记录。 SaveChanges 本质上是事务性的,将您的 for 循环放在上下文中,然后对 SaveChanges 进行一次调用,即

using (OptimusEntities opt = new OptimusEntities())
{
    foreach(var item in obcollection)
    {
        ...
    }
    opt.SaveChanges();
}

此外,您似乎在执行插入之前进行了各种查询,这导致每个请求 1 次访问数据库。如果您打算进行批量插入,我建议您使用 SqlBulkCopy 类,因为它是 far more efficient

【讨论】:

  • 谢谢..我试试看,让你知道性能的变化
  • @ElectricRouge 您应该会发现它总体上要快得多,但是,尝试使用 EF 一次性批量提交 1000s 条记录永远不会超级快,最好使用 @987654326 @ 或小批量提交。
  • 我根据您和 Patryk Ćwiek 的建议对我的代码进行了更改。现在它已经下降到大约 7 分钟。我还没试过SqlBulkCopy。我知道7分钟还是太多了。我为获取少数字段而进行的数据库调用需要时间。有没有其他方法可以做到这一点。
  • @ElectricRouge SqlBulkCopy 将为您提供您所追求的性能目标。
  • 除了SqlBulkCopy之外,如果我编写存储过程来保存并调用它而不是通过EF保存会更快
猜你喜欢
  • 1970-01-01
  • 2012-02-18
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
  • 1970-01-01
  • 2013-12-01
  • 1970-01-01
相关资源
最近更新 更多