C# 如何在实体框架中处理过时的缓存?
我从实体框架中得到了非常奇怪的行为。我正在编写一个WebApi应用程序,以便断开/分离从浏览器获取的对象。我得到的数据是事务性的,因此它与数据库中的任何给定表都不匹配。我必须进行大量的查找和数据操作,以获得数据库的实际更新 我似乎遇到的问题是,在查询数据时,我正在填充跟踪的更改缓存。这对我来说似乎不是问题,因为数据的真正来源应该是数据库。当我最终进行数据更改并调用SaveChanges时,会出现约束错误。这是我的步骤C# 如何在实体框架中处理过时的缓存?,c#,entity-framework,asp.net-web-api,C#,Entity Framework,Asp.net Web Api,我从实体框架中得到了非常奇怪的行为。我正在编写一个WebApi应用程序,以便断开/分离从浏览器获取的对象。我得到的数据是事务性的,因此它与数据库中的任何给定表都不匹配。我必须进行大量的查找和数据操作,以获得数据库的实际更新 我似乎遇到的问题是,在查询数据时,我正在填充跟踪的更改缓存。这对我来说似乎不是问题,因为数据的真正来源应该是数据库。当我最终进行数据更改并调用SaveChanges时,会出现约束错误。这是我的步骤 查询数据 创建要插入的行 将行与数据库进行比较,并对数据库进行更改 在查看Ct
var details = oldInvoice.details.ToList();
Context.Entry(oldInvoice).State = EntityState.Unchanged;
Context.Entry(oldInvoice).State = EntityState.Deleted;
details.ForEach(a => Context.Entry(a).State = EntityState.Deleted);
实体框架提供了一个异常
DbUpdateConcurrencyException
,您可以在调用SaveChanges()
时捕捉到该异常。您可以循环处理错误,如下所示:
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
// Get the current entity values and the values in the database
var entry = ex.Entries.Single();
var currentValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
// Choose an initial set of resolved values. In this case we
// make the default be the values currently in the database.
var resolvedValues = databaseValues.Clone();
// Have the user choose what the resolved values should be
HaveUserResolveConcurrency(currentValues, databaseValues,
resolvedValues);
// Update the original values with the database values and
// the current values with whatever the user choose.
entry.OriginalValues.SetValues(databaseValues);
entry.CurrentValues.SetValues(resolvedValues);
}
} while (saveFailed);
此外,您的更新代码听起来也很可疑。通常,当您通过WebApi或其他机制将数据传递给客户机时,返回的数据没有跟踪数据,因此您应该检查它是否存在,并将其重新附加到上下文中,并将其状态更改为
EntityState。在调用SaveChanges()之前修改如果存在
将上下文保留很长一段时间是个坏主意,因为当跟踪图中包含大量实体时,跟踪图的性能不好。我的建议是不要在请求之间重复使用上下文。这也可以避免任何并发的更新问题,谢谢你的回答。关于丢失的跟踪数据,您是正确的。所以我完全按照你在下面描述的做。除了前面的查询弄乱了跟踪数据。