我必须维护一个创建和管理报价的应用程序。 (报价是包含定价所需信息的单个类。)
大多数情况下,创建报价意味着在几个表中添加几行。它很快。但是,有时用户会将大量索赔附加到报价单中,并且必须在数据库中创建数万行。使用EF,它需要永远。
所以我尝试使用DbBulkCopy批量插入声明,同时使用EF来管理报价的提醒,但我弄清楚如何实现这一点的方式真的非常麻烦:我不得不克隆报价,分离历史记录,从数据库中删除声明,保存报价单,获取新的外键,批量创建声明,将历史记录附加到报价单等。
这是实现这个目标的另一种方式吗?
注意:我可以将声明历史记录与Quotation类分开并使用ADO管理第一个,然后使用EF管理,但很多现有流程需要实际的类设计(更不用说用户实际上可以附加许多声明历史,当然,是深埋在对象树中的子集的子集的子集......)。
非常感谢, 西尔。
答案 0 :(得分:1)
我找到了一种简单的方法来实现这一目标:
// We will need a quotation Id (see below). Make sure we have one
SaveQuotation( myQuotation );
// Read the large claim history
var claimCollection = ImportClaimsFromExcelFile( fileName );
// Save the claim history without using EF. The quotation Id is needed to
// link the history to the quotation.
SaveClaimCollectionUsingSqlBulkCopy( claimCollection, myQuotation.Id );
// Now, ask EF to reload the quotation.
LoadQuotation( myQuotation.Id );
有60 000个声明的历史记录,此代码在10秒内运行。使用myObjectContext.SaveChanges()
,10分钟甚至不够......
感谢您的建议!
注意:以下是我用于批量插入声明的代码:
using (var connection = new SqlConnection(constring))
{
connection.Open();
using (var copy = new SqlBulkCopy(connection))
{
copy.DestinationTableName = "ImportedLoss";
copy.ColumnMappings.Add("ImporterId", "ImporterId");
copy.ColumnMappings.Add("Loss", "Loss");
copy.ColumnMappings.Add("YearOfLoss", "YearOfLoss");
copy.BatchSize = 1000;
copy.WriteToServer(dt);
}
connection.Close();
}
答案 1 :(得分:0)
由于为了坚持实体而对数据库进行了多次往返,因此EF不是批量操作的最佳选择。这说起来看起来EF团队正在考虑改进这个http://entityframework.codeplex.com/workitem/53
另外,请看一下:http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/。 另一种可能的解决方案是在一个 ExecuteSqlCommand 中添加所有插入,但是你将失去使用ORM的所有优点。