.net SQL Server CE 4.0和Entity Framework 4.2的批插入性能非常差
我使用EntityFramework4.2(代码优先)将大量数据插入SQLServerCE4.0,与直接SQL插入相比,性能非常差 模型非常简单:.net SQL Server CE 4.0和Entity Framework 4.2的批插入性能非常差,.net,performance,entity-framework,sql-server-ce-4,.net,Performance,Entity Framework,Sql Server Ce 4,我使用EntityFramework4.2(代码优先)将大量数据插入SQLServerCE4.0,与直接SQL插入相比,性能非常差 模型非常简单: public class DocMember { public DocMember() { this.Items = new List<DocItem>(); } public int Id { get; set; } public string Name { get; set; } public st
public class DocMember
{
public DocMember() { this.Items = new List<DocItem>(); }
public int Id { get; set; }
public string Name { get; set; }
public string MemberType { get; set; }
public string AssemblyName { get; set; }
public virtual IList<DocItem> Items { get; set; }
}
public class DocItem
{
public int Id { get; set; }
public DocMember Member { get; set; }
public string PartType { get; set; }
public string PartName { get; set; }
public string Text { get; set; }
}
我可以理解EF有一点开销,但是它比SQL慢了65倍
也许我的代码中有一个问题,但它非常简单,我看不出有什么可能是错误的:
private TimeSpan ImportMembersEF(IList<DocMember> members)
{
using (var db = new DocEntities())
{
db.Database.CreateIfNotExists();
var sw = Stopwatch.StartNew();
foreach (var m in members)
{
db.Members.Add(m);
}
db.SaveChanges();
sw.Stop();
return sw.Elapsed;
}
}
private TimeSpan ImportMembersEF(IList成员)
{
使用(var db=new DocEntities())
{
db.Database.CreateIfNotExists();
var sw=Stopwatch.StartNew();
foreach(成员中的var m)
{
db.成员。添加(m);
}
db.SaveChanges();
sw.Stop();
返回经过的开关;
}
}
我还尝试为每个插入的项目调用SaveChanges
,或者每100或200个项目调用一次,但都没有效果(这实际上会让情况变得更糟)
有没有办法提高性能,还是必须使用SQL进行批插入
编辑:为了完整起见,下面是SQL插入的代码:它很慢,因为它没有批处理插入 在db上插入using identity时,它必须在分配给模型的每个项目之后选择结果ID。这使得它非常慢 您的adhoc SQL没有选择出ID,因此在批处理时,您可以一次提交所有语句 用NHibernate编写的Altho:
我写了关于使用ORM生成的ID和SQL生成的ID的文章 您可以使用我的SqlCeBulkCopy库加载批量数据,它模仿SqlBulkCopy api:服务器上是否自动生成
Id
s?我不知道这是否与性能缓慢有关,但我想知道,根据惯例,公共DocMemeber成员{get;set;}
应该是public virtual DocMember DocMember{get;set;}
以及是否应该有一个成员public int DocMember DocMemberId{get;set;}
@Eranga,是。我没有对此做任何说明,这是默认行为。@DanM,我尝试了您建议的更改,但没有更好。无论如何,只有当您从数据库加载数据时,才可以将此成员设置为虚拟成员,而不是在插入数据时。我将尝试不使用自动生成的Id,并尝试使用使用单独的上下文插入每个成员-两者都只是为了诊断问题。我的adhoc SQL也不是批量插入,而是检索Id。。。我将更新这个问题。是在每次插入后选择ID并将其分配给模型吗?有趣的是,这肯定很奇怪。我可能会在回家后打开DotTrace看看这个。临时sql总是会更快,但会更快吗?EF的速度有点奇怪…谢谢,但它没有回答我的问题。。。如果我在SQL中这样做,我不会有性能问题(尽管它可能会通过使用大容量复制得到改进),我的问题是实体框架。实际上,我注意到了一些有趣的事情:“WriteToServer方法还接受DataTable、IEnumerable或和IEnumerable”。它是否接受POCO,或者它必须是EF生成的实体?不,它可以是任何对象列表,即POCOsHi Erik,我刚刚找到时间尝试这个解决方案。这真的很快,但有一个问题:我的ID是自动生成的,SqlCeBulkCopy不会用生成的值更新我的实体。。。有办法解决吗?不确定您的意思是什么-您可以通过选项(BulkCopyOptions枚举)设置身份处理?
private TimeSpan ImportMembersEF(IList<DocMember> members)
{
using (var db = new DocEntities())
{
db.Database.CreateIfNotExists();
var sw = Stopwatch.StartNew();
foreach (var m in members)
{
db.Members.Add(m);
}
db.SaveChanges();
sw.Stop();
return sw.Elapsed;
}
}