2014-02-11 48 views
0

我想清楚了ObjectStateManager,这样的的DbContext调用SaveChanges();后下面的行不返回结果:如何清除ObjectStateManager

dbContext.ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged); 

的行为似乎是所有对象(添加,修改)在ObjectStateManager中将状态更改为Unchanged,所以代码将全部返回。有没有办法清除它?

我需要这个,因为我重新使用上下文并为实体带来了不变的状态,但由于ObjectSateManager增长并随着不变的实体增长(因为它在SaveChanges之后将它们全部更改为不变),因此,一个实体一遍又一遍。

编辑:

为什么分离方法心不是为我工作:

假设您有2类:

public class Nation 
{ 
    public string Name { get; set; } 
    public ICollection<City> Cities { get; set; } 
} 

public class City 
{ 
    public string Name { get; set; } 
    public Nation Nation { get; set; } 
} 

现在我已经传送到的SaveChanges一个国家项目与一些城市需要更新或插入。

让我们假设如下:

var canada = new Nation() 
{ 
    Name = "Canada", 
} 

canada.Cities = new City[] 
    { 
     new City(){ Name = "Ottawa", Nation = canada, }, 
     new City(){ Name = "Edmonton", Nation = canada, }, 
     new City(){ Name = "Victoria", Nation = canada, }, 
     new City(){ Name = "Torronto", Nation = canada, } 
    }, 
} 

现在,我有我的ObjectStateManager内不变的状态所有这些对象。 (SaveChanges调用后)

我比他们通过循环并设置状态不变,这个结果在每个城市有Nation = nullNation.Cities being empty。此外

dbContext.ObjectContext.Detach(entity); 

,如果你不是需要连接的实体,则可以使用AsNoTracking()扩展方法:

+2

您应该保持尽可能短的时间。在整个应用程序中共享/重用上下文是一个坏主意。 – MarcinJuraszek

+0

@MarcinJuraszek我正在做一个Import方法,它调用每个元素的SaveChanges,因为我想获得每个结果的即时反馈,因为整个Import总共有10.000个实体来保存,我相信使用一个上下文和一个事务是比试图用1创建10.000个上下文更好? transcation进行完全回滚。 –

+0

你需要分离的实体是什么?一旦他们得救,你是不是完成了与他们的合作? – ivowiblo

回答

0

我发现了一个解决方案,对我来说“完美”,它不清除ObjectStateManger,但忽略所有以前连接/处理的实体。

private static int __lastProcessedIndex = 0; 
private static DbContext _oldContext = null; 

public void DoYourMagic(DbContext context) 
{ 
    if (ReferenceEquals(context, _oldContext) == false) 
    { 
     _oldContext = context; 
     _lastProcessedIndex = 0; 
    } 

    var objectContext = (context as IObjectContextAdapter).ObjectContext; 
    var unchanged = objectContext.ObjectStateManager.GetObjectSateEntires(EntityState.Unchanged).ToArray(); 

    for (int i = _lastProcessedIndex; i < unchanged.Length; i++) 
    { 
     //do your magic with unchanged entities... 
    } 

    context.SaveChanges(); 

    //Now all entries in objectstatemanager are in state Unchanged 
    //I am setting the index to the Count() - 1 
    //So that my next call of the method "DoYourMagic" starts the for with this index 
    //This will than ignore all the previously attached ones 
    _lastProcessedIndex = objectContext.ObjectStateManager.GetObjectSateEntires(EntityState.Unchanged).Count(); 
} 
+0

问题在于它没有缩放你是否真的从数据库中加载10k对象而不处理它们?这个数字有可能增长吗? – ivowiblo

+0

是的,我正在加载这些数据,并且没有数字不会增长,这是最大的非常非常罕见的东西,根本不可能 - 更可能是大约3.000。 –

+0

@ivowiblo忘了(a)xxxx,看看我的先前的评论。 SRY。 –

0

ObjectContextDetach方法将从对象上下文中删除。它将执行没有跟踪的查询:

var items = dbContext.Items.AsNoTracking().Where(...); 
+0

我有尝试了detach方法,但不幸的是这也改变了相关的导航属性。任何其他的想法? –

+0

你是什么意思“更改相关导航属性”? – ivowiblo

+0

看到我在编辑中的问题 –

0

你可以做的是使用分页。每N个对象创建一个新的DbContext,但所有这些对象都使用相同的连接和事务。