asp.net mvc ef codefirst存储库并发无法正常工作

时间:2012-06-13 13:45:12

标签: asp.net-mvc entity-framework exception concurrency code-first

我有一个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() });
    }

1 个答案:

答案 0 :(得分:1)

早上好朋友。 您应该在control concurrency上添加有关您想要的属性的信息。

示例:

[ConcurrencyCheck]
     public int Code {get; set;}