我正在使用EF5,并将POCO实体的断开连接图附加到我的上下文中,如下所示:
using (var context = new MyEntities())
{
context.Configuration.AutoDetectChangesEnabled = false;
context.MyEntities.Attach(myEntity);
// Code to walk the entity graph and set each entity's state
// using ObjectStateManager omitted for clarity ..
context.SaveChanges();
}实体"myEntity“是一个很大的实体图,有许多子集合,子集合又有自己的子集合,依此类推。整个图包含10000个实体的顺序,但通常只有一小部分被改变。
设置实体状态和实际SaveChanges()的代码相当快(<200ms)。这里的问题是Attach(),它需要2.5秒,所以我想知道这是否可以改进。我看过一些文章告诉您设置AutoDetectChangesEnabled = false,我在上面就是这么做的,但在我的场景中没有什么不同。为什么会这样呢?
发布于 2013-05-01 19:58:26
我担心2.5秒附加一个包含10000个实体的对象图是“正常的”。这可能是当您附加图形时发生的实体快照创建。
如果“通常只更改一小部分”--比如说100个--您可以考虑从数据库中加载原始实体并更改其属性,而不是附加整个图,例如:
using (var context = new MyEntities())
{
// try with and without this line
// context.Configuration.AutoDetectChangesEnabled = false;
foreach (var child in myEntity.Children)
{
if (child.IsModified)
{
var childInDb = context.Children.Find(child.Id);
context.Entry(childInDb).CurrentValues.SetValues(child);
}
//... etc.
}
//... etc.
context.SaveChanges();
}虽然这将创建大量的单一数据库查询,但只会加载没有导航属性的“平面”实体,并且附加(在调用Find时发生)不会消耗太多时间。要减少查询的数量,您还可以尝试使用Contains查询加载与“批处理”相同类型的实体:
var modifiedChildIds = myEntity.Children
.Where(c => c.IsModified).Select(c => c.Id);
// one DB query
context.Children.Where(c => modifiedChildIds.Contains(c.Id)).Load();
foreach (var child in myEntity.Children)
{
if (child.IsModified)
{
// no DB query because the children are already loaded
var childInDb = context.Children.Find(child.Id);
context.Entry(childInDb).CurrentValues.SetValues(child);
}
}这只是一个简化的例子,假设你只需要改变实体的标量属性。如果修改关系(子项已被添加到集合和/或从集合中删除等),它可能会变得任意复杂。都有牵连。
https://stackoverflow.com/questions/16304009
复制相似问题