C# 如何清除ObjectStateManager
我想清除ObjectStateManager,以便在调用C# 如何清除ObjectStateManager,c#,entity-framework,objectstatemanager,C#,Entity Framework,Objectstatemanager,我想清除ObjectStateManager,以便在调用SaveChanges()之后在DbContext上,以下行不返回任何结果: dbContext.ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged); 其行为似乎是ObjectStateManager中的所有对象(添加、修改)都将状态更改为未更改,因此代码将返回所有对象。有没有办法清除它 我需要这样做,因为我正在重用上下文并为状态不变的
SaveChanges()之后
在DbContext上,以下行不返回任何结果:
dbContext.ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged);
其行为似乎是ObjectStateManager中的所有对象(添加、修改)都将状态更改为未更改
,因此代码将返回所有对象。有没有办法清除它
我需要这样做,因为我正在重用上下文并为状态不变的实体做一些事情,但是由于ObjectSateManager随着不变的实体不断增长(因为它在SaveChanges之后将它们全部更改为Unchanged),它对一个实体反复做同样的工作
编辑:
为什么分离方法对我不起作用:
假设您有两个类:
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; }
}
现在,在ObjectStateManager中,所有这些对象都处于未更改状态。(在SaveChanges调用之后)
然后我循环遍历它们并将状态设置为未更改,这将导致每个城市都有
Nation=null
和Nation.Cities为空
ObjectContext
的Detach
方法将其从对象上下文中删除:
dbContext.ObjectContext.Detach( entity );
此外,如果不需要附加实体,可以使用AsNoTracking()
扩展方法。它将执行查询而不跟踪:
var items = dbContext.Items.AsNoTracking().Where(...);
您可以做的是使用分页。每N个对象创建一个新的
DbContext
,但所有对象都使用相同的连接和事务。我找到了一个“完美”的解决方案,它不清除ObjectStateManager,而是忽略所有以前附加/处理的实体
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();
}
private static int\uu lastProcessedIndex=0;
私有静态DbContext _oldContext=null;
public void DoYourMagic(DbContext上下文)
{
if(ReferenceEquals(context,_oldContext)==false)
{
_oldContext=上下文;
_lastProcessedIndex=0;
}
var objectContext=(上下文为IObjectContextAdapter);
var unchanged=objectContext.ObjectStateManager.GetObjectSateEntries(EntityState.unchanged).ToArray();
for(int i=_lastProcessedIndex;i
您应该尽可能少地打开上下文。在整个应用程序中共享/重用上下文是个坏主意。@MarcinJuraszek我正在执行一个导入方法,该方法调用每个元素的SaveChanges,因为我想立即获得每个结果的反馈,因为整个导入总共有10.000个实体要保存,我相信使用一个上下文,一个事务比尝试用1创建10000个上下文要好?完全回滚的Transaction。您需要分离的实体做什么?他们获救后,你就不再和他们合作了吗?@ivowiblo很遗憾,我仍然需要他们(这是我老板给我的应用程序要求的一部分,这迫使我做一些实体框架不友好的事情,但我已经找到了一个适合我的解决方案,请看我的答案。我尝试了分离方法,但遗憾的是,这也改变了相关的导航属性。还有其他想法吗?你对分离的意思是什么“更改相关的导航属性"?问题是它根本不可伸缩。你真的从数据库中加载了10k个对象而没有处理它们吗?这个数字可能会增加吗?是的,我正在加载这些对象,但不,这个数字没有增加,这是最大值,很少有这么大的对象-更有可能是大约3000个。@ivowiblo忘记了(a)xxxx,请参阅我之前的评论。sry。
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();
}