我有一个asp.net mvc应用程序,我使用EF CodeFirst和存储库模式,我正在尝试测试并捕获DbUpdateConcurrencyException,但它似乎没有触发,晚上虽然我在一个浏览器中更新记录虽然它已经在另一个中打开,然后转到另一个并尝试更新相同的记录,它允许我这样做。我在表上有一个TimeStamp列(称为RowVersion),它随每次更新而改变,所以这是正确的,并且从观看sql profiler我可以看到update语句确实检查时间戳是传入的内容,所以我'我没有想法,到目前为止我找不到任何可以帮助我的东西。如果有人能看到我做错了什么,请告诉我。谢谢!
这是我的实体:
public class MyEntity : EntityBase
{
public override int Id { get; set; }
public DateTime? LastEdited { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
这是存储库及其基类/ dbcontext:
public class MyEntityDataProvider : EfDataProviderBase<MyEntity>, IMyEntityDataProvider
{
public MyEntityDataProvider (IDataContext dataContext) : base(dataContext) { }
}
public abstract class EfDataProviderBase<T> : DataProviderBase<T> where T : EntityBase
{
public new DbDataContext DataContext
{
get { return base.DataContext as DbDataContext; }
protected set { base.DataContext = value; }
}
public EfDataProviderBase(IDataContext dataContext)
: base(dataContext)
{
if (!(dataContext is DbDataContext)) throw new ArgumentException("Parameter 'dataContext' must be of type DbDataContext.");
}
public override T GetById(int id)
{
if (id < 1) return null;
return this.DataContext.GetDbSet<T>().Find(id);
}
public override List<T> GetAll()
{
return this.DataContext.GetDbSet<T>().OrderBy(e => e.Id).ToList();
}
public override void Insert(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
this.DataContext.GetDbSet<T>().Add(entity);
}
public override void Update(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
if (!this.DataContext.GetDbSet<T>().Local.Any(e => e.Id == entity.Id))
this.DataContext.GetDbSet<T>().Attach(entity);
this.DataContext.Entry(entity).State = EntityState.Modified;
}
}
public class DbDataContext : DbContext, IDataContext
{
public DbSet<MyEntity> MyEntities { get; set; }
public DbSet<T> GetDbSet<T>() where T : EntityBase
{
Type entityType = typeof(T);
if (entityType == typeof(User))
return this.Users as DbSet<T>;
}
public void Commit()
{
this.SaveChanges();
}
}
public abstract class DataProviderBase<T> : IDataProvider<T> where T: EntityBase
{
public IDataContext DataContext { get; protected set; }
public DataProviderBase(IDataContext dataContext)
{
if (dataContext == null) throw new ArgumentNullException("dataContext");
this.DataContext = dataContext;
}
public abstract T GetById(int id);
public abstract List<T> GetAll();
public void Save(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
if (entity.IsNew)
{
this.Insert(entity);
}
else if (entity.IsDeleted)
{
this.Delete(entity);
}
else
{
this.Update(entity);
}
}
public abstract void Insert(T entity);
public abstract void Update(T entity);
}
这是我的控制器动作:
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult UpdateViewModel(ViewModel model)
{
if (ModelState.IsValid)
{
try
{
MyEntity current = this.MyEntityDataProvider.GetById(model.Id);
current.LastEdited = DateTime.UtcNow;
current.RowVersion = model.Timestamp; // should have original timestamp, getting from hidden field on view
this.MyEntityDataProvider.Save(current);
this.DataContext.Commit(); // one dbcontext per http request, injected by ninject
return Json(new { success = "Saved!" });
}
catch (DbUpdateConcurrencyException)
{
ModelState.AddModelError("", "This record has been edited by an another person since you have opened it - please close and re-open to attempt your changes again.");
}
}
return Json(new { errors = GetErrorsFromModelState() });
}
答案 0 :(得分:1)