在实体框架中 EntityState.Detached 使操作变慢
Posted
技术标签:
【中文标题】在实体框架中 EntityState.Detached 使操作变慢【英文标题】:In Entity Framework EntityState.Detached makes operation slow 【发布时间】:2020-05-25 20:00:57 【问题描述】:在调试以下代码时,我发现 forEach 需要花费大量时间,将 6000 条记录的状态从 EntityState.Unchanged
更改为 EntityState.Detached
在我的本地开发环境中大约需要 16 分钟。
'where' 表达式正在过滤记录,而 'update' 表达式仅更新单个列。
我尝试将 ProxyCreationEnabled 和 LazyLoadingEnabled 设置为 false,但仍然需要相同的时间。这段代码有什么问题?
DbSet = Context.Set<T>();
...
...
public virtual int UpdateDB(Expression<Func<T, T>> update, Expression<Func<T, bool>> where)
var recordsUpdated = DbSet.Where(where).Update(update);
foreach (var e in DbSet.Where(where))
var state = Context.Entry(e).State;
Context.Entry(e).State = EntityState.Detached;
state = Context.Entry(e).State;
return recordsUpdated;
【问题讨论】:
这个 Update 方法到底发生了什么?我怀疑你在那里打电话给SaveChanges
并且有一些你试图“重置”的静态上下文。这是几种不良做法的结合。
@GertArnold 在这段代码中,我们尝试使用 where 和 update 表达式直接更新 DbSet。我发现var recordsUpdated = DbSet.Where(where).Update(update);
行执行得非常快,但是Context.Entry(e).State = EntityState.Detached;
行似乎需要更多时间循环每条记录,这里我们试图将状态从未更改更改为已分离。
这并不能真正回答我的问题。我试图找出你为什么要做你正在做的事情。您不需要将状态设置为分离。它可能使更改跟踪器非常忙碌(在臃肿的上下文中一直调用 DetectChanges)。您应该简单地处理上下文。这种更新,如果使用 EF 完成,应该通过创建存根实体来完成。
@GertArnold 很抱歉我对 EF 世界很陌生。我正在尝试分离实体,以便 EF 不跟踪它,但这看起来是个非常糟糕的主意,因为它使更改跟踪器保持忙碌。我将阅读更多关于处理上下文的内容。谢谢。
【参考方案1】:
这段代码有什么问题?
那个代码很昂贵而且没有意义。
这个
var recordsUpdated = DbSet.Where(where).Update(update);
似乎正在从数据库中获取每一行并通过Update
函数运行。那么这个
foreach (var e in DbSet.Where(where))
正在从数据库中获取每一行再次,但是将它们全部与跟踪的实体进行匹配,并返回跟踪的实体,而不是它刚刚从数据库中获取的实体。实体条目的状态被翻转为分离并返回到之前的状态。
你想完成什么?
如果要更新表中的每一行,请直接使用 SQL。不要将它们全部获取给客户端,更改它们并保存回来。
【讨论】:
以上是关于在实体框架中 EntityState.Detached 使操作变慢的主要内容,如果未能解决你的问题,请参考以下文章