[英]Entity Framework Optimistic Concurrency Exception not occuring
我们有一个ASP.Net MVC应用程序,它使用EF4作为其数据访问层,我们看到在我们认为它们应该是没有抛出OptimisitcConcurrencyExceptions的意外行为。
我们已将问题简化为以下代码...
using System.Linq;
using Project.Model;
namespace OptimisticConcurrency
{
class Program
{
static void Main()
{
Contact firstContact = null;
using (var firstEntities = new ProjectEntities())
{
firstContact = (from c in firstEntities.Contacts
where c.LastName == "smith" select c).Single();
}
using (var secondEntities = new ProjectEntities())
{
var secondContact = (from c in secondEntities.Contacts
where c.LastName == "smith" select c).Single();
secondContact.Title = "a";
secondEntities.SaveChanges();
}
firstContact.Title = "b";
using (var thirdEntities = new ProjectEntities())
{
var thirdContact = (from c in thirdEntities.Contacts
where c.LastName == "smith" select c).Single();
thirdContact.Title = firstContact.Title;
//EXPLICITLY SET VERSION HERE
thirdContact.Version = firstContact.Version;
thirdEntities.SaveChanges();
}
}
}
}
这是我们的MVC应用程序中发生的相当简单的版本,但是会出现同样的问题。
当我们在第三个Entity上调用SaveChanges时,我期待异常并没有抛出任何东西。
更有趣的是,当我们附加SQL事件探查器时,我们看到版本正在where子句中使用,但它是使用的第三个实体版本值(当前数据库中的值),而不是第一个实体值DESPITE它立即显式设置在调用SaveChanges之前。 SaveChanges正在将版本重置为检索的值而不是设置值。
在EDMX中,Version设置为StoreGeneratedPattern设置为Computed。
任何人都知道这里发生了什么?
这是个问题。 将列设置为Computed
您无法在应用程序中设置其值(您可以但不使用该值)。
编辑:
如果从数据库加载实体,则默认情况下会跟踪上下文。 上下文存储其原始值。 原始值例如用于快照更改跟踪,但它们也用作Computed
属性的唯一有效源。 如果在实体中设置Computed
属性,则不使用该值,并使用insted原始值。 解决方法是修改原始值(在修改其他任何内容之前):
using (var context = new TestEntities())
{
var entityToUpdate = context.MyEntities.Single(e => e.Id == someId);
entityToUpdate.Timestamp = entity.Timestamp;
ObjectStateEntry entry = context.ObjectStateManager.GetObjectStateEntry(entityToUpdate);
entry.ApplyOriginalValues(entityToUpdate);
// set modified properties
context.SaveChanges();
}
编辑2:
顺便说一句。 一旦您同时拥有实际加载的时间戳和先前检索的时间戳,您只需在应用程序中比较它们,而不是在数据库中进行比较。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.