在Ef - UnitOfWork中编辑实体

时间:2013-03-28 12:19:50

标签: asp.net-mvc entity-framework c#-4.0 unit-of-work

我正在将此模板用于我的项目

   public interface IUnitOfWork
    {
        IDbSet<TEntity> Set<TEntity>() where TEntity : class;
        int SaveChanges();
        void RejectChanges();
        DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
    }

实现:

  public   class BookStoreDbContext : DbContext, IUnitOfWork

  {

    public DbSet<Categori> Categoris { get; set; }


    public new DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class
    {
        return base.Entry(entity);

    }

    public override int SaveChanges()
    {

        return base.SaveChanges();
    }

的Controler:

 public class CategoriController : Controller
   {

    private IUnitOfWork _uw;

    private ICategoriService _categoriService;


    public CategoriController(IUnitOfWork uw,ICategoriService categoriservice )
    {
        _uw = uw;
        _categoriService = categoriservice;
    }




   public ActionResult Edit(int id = 0)
    {
        var categori = _categoriService.Find(i => i.Id == id);
        if (categori == null)
        {
            return HttpNotFound();
        }
        return View(categori);
    }

    [HttpPost]
    public ActionResult Edit(Categori categori)
    {
        if (ModelState.IsValid)
        {

              _uw.Entry(categori).State = EntityState.Modified;
                _uw.SaveChanges();
        }
        return View(categori);
    }
}

存储库或服务层:

 public interface IGenericService<T> : IDisposable where T : class
    {
    void Add(T entity);

    void Delete(T entity);
    T Find(Func<T, bool> predicate);
    IList<T> GetAll();
    IList<T> GetAll(Func<T, bool> predicate);


    }




 public interface ICategoriService : IGenericService<DomainClasses.Models.Categori>
   {

   }

impliment repository:

 public class EfGenericService<TEntity> : IGenericService<TEntity> where TEntity : class
{
    protected IUnitOfWork _uow;
    protected IDbSet<TEntity> _tEntities;



    public EfGenericService(IUnitOfWork uow)
    {
        _uow = uow;
        _tEntities = _uow.Set<TEntity>();
    }


    public virtual void Add(TEntity entity)
    {
        _tEntities.Add(entity);
    }

    public void Delete(TEntity entity)
    {
        _tEntities.Remove(entity);
    }

    public TEntity Find(Func<TEntity, bool> predicate)
    {
        return _tEntities.Where(predicate).FirstOrDefault();
    }

    public IList<TEntity> GetAll()
    {
        return _tEntities.ToList();
    }

    public IList<TEntity> GetAll(Func<TEntity, bool> predicate)
    {
        return _tEntities.Where(predicate).ToList();
    }



 public class EfCategoriService : EfGenericService<Categori>,ICategoriService
{
      public EfCategoriService(IUnitOfWork uow)
        : base(uow)
      {
    }


}

Global.asax

 private static void InitStructureMap()
    {
        ObjectFactory.Initialize(
            x =>
                {
                    x.For<IUnitOfWork>().HttpContextScoped().Use(() => new BookStoreDbContext());
                     x.ForRequestedType<ServiceLayer.Interfaces.ICategoriService>()
                     .TheDefaultIsConcreteType<EfCategoriService>();

}

但是我在更新实体时遇到了这个错误:

存储更新,插入或删除语句会影响意外的行数(0)。自实体加载后,实体可能已被修改或删除。刷新ObjectStateManager条目

请帮我解决此错误?

1 个答案:

答案 0 :(得分:1)

您的摘要中唯一相关的行是:

_uw.Entry(categori).State = EntityState.Modified;
_uw.SaveChanges();

现在,看看你得到的例外:

  

存储更新,插入或删除语句会影响意外   行数(0)。自那以后,实体可能已被修改或删除   实体已加载。

  • 是否将实体状态设置为Modified 插入实体?否。
  • 是否删除实体?否。
  • 是否更新实体?是

  • EF尝试更新的实体是否已已删除?好吧,也许吧。怎么检查?删除实体时,数据库必须知道密钥才能知道要删除的行。要确认密钥是否正确在控制器发布操作中使用调试器,请检查传递给方法的categori的密钥值。它有预期的价值吗?如果没有,您可能在视图中遇到问题,或者将表单和路由值绑定到categori模型。如果是,请检查数据库中是否具有该键的实体位于数据库表中。如果是,则下一点。

  • 该实体是否已经修改?如果您在Categori模型中将另一个属性标记为并发令牌,则可能会发生EF“认为”它已在数据库中进行了修改(即使它没有)。如果在GET请求中加载实体并在POST请求中重新附加(将状态设置为Modified)和SaveChanges之间,数据库或视图中的属性已更改你会得到并发违规。

优先考虑上面的粗体测试,因为在我看来,这是问题的最可能原因。如果事实证明密钥没有更好的预期值,那么请问一个新问题,因为它将是一个纯粹的ASP.NET MVC问题,与EF和你的UOW和服务架构无关。