我已经处理了2天而且找不到解决方案。
using (TaxablePersonContext context = new TaxablePersonContext(this.ConnectionString))
{
context.Configuration.AutoDetectChangesEnabled = false;
foreach(TaxablePerson p in persons) // Persons has always size 1000
{
// TaxablePerson has some other properties e.g. Name, VatId, Street,...
p.RecCreatedBy = "application name";
p.RecCreatedOn = this.SynchronizationStartDateTime;
p.RecModifiedBy = "application name";
p.RecModifiedOn = this.SynchronizationStartDateTime;
p.RecSyncDate = this.SynchronizationStartDateTime;
p.RecActive = true;
}
DateTime start1 = DateTime.Now;
context.TaxablePersons.AddRange(persons);
TimeSpan end1 = DateTime.Now.Subtract(start1);
DateTime start2 = DateTime.Now;
context.SaveChanges();
TimeSpan end2 = DateTime.Now.Subtract(start1);
}
我需要将近10秒的时间来插入1000条记录,并且需要98秒才能在sql server中插入10.000条记录。您能否建议如何改进实体框架插入性能。我阅读了这篇文章Fastest Way of Inserting in Entity Framework并包含了这篇文章中提到的提示,但仍然插入很慢。我需要插入260.000条记录需要52分钟。我正在以1000的批量插入,上面的代码演示了。从文件中读取数据,当我点击1000条记录时,我会与数据库进行同步。我还可以做些什么?有人提到使用时设置context.Configuration.AutoDetectChangesEnabled = false;性能从几分钟提高到几乎几秒钟。我错过了什么?我正在使用实体框架6.1.3。
答案 0 :(得分:0)
使用sql profiler,我发现Entity框架逐个发送查询,例如
INSERT INTO MyTable (id, name) VALUES (1, 'Bob')
INSERT INTO MyTable (id, name) VALUES (2, 'Peter')
INSERT INTO MyTable (id, name) VALUES (3, 'Joe')
所以实际上sql server在这种情况下执行1000次插入非常慢 - 差不多10秒(虽然在事务中执行)。然后我构造了具有多个值的插入 - 具有多个值的SQL并且插入1000个记录花费了5秒(50%更好 - 更早10秒)。 Sql server有一个你可以传递的sql参数限制,即2100,所以这是你用这种方法做的最好的。
private void MultiRecordsInsert(TaxablePersonContext context, List<TaxablePerson> personsToAdd)
{
List<SqlParameter> parameters = new List<SqlParameter>();
string firstQuery = @"insert into TaxablePerson (c1, c2, c3) values ";
string query = firstQuery;
for (int i = 0; i < personsToAdd.Count; i++)
{
query += "(@c1" + i.ToString();
query += ",@c2" + i.ToString();
query += ",@c3" + i.ToString() + "),";
parameters.Add(new SqlParameter("@c1" + i.ToString(), personsToAdd[i].c1));
parameters.Add(new SqlParameter("@c2" + i.ToString(), personsToAdd[i].c2));
parameters.Add(new SqlParameter("@c3" + i.ToString(), personsToAdd[i].c3));
// table has 16 columns (I reduced here for simplicity) so: 2100 / 16 = 131,
// used 100
//
if (i % 100 == 0)
{
query = query.Substring(0, query.Length - 1); // remove last comma
context.Database.ExecuteSqlCommand(query, parameters.ToArray());
query = firstQuery;
parameters = new List<SqlParameter>();
}
}
if (parameters.Count > 0) // what is left
{
query = query.Substring(0, query.Length - 1);
context.Database.ExecuteSqlCommand(query, parameters.ToArray());
}
}