【问题标题】:Entity Framework CreateObjectset Attach method not updating实体框架 CreateObjectset Attach 方法未更新
【发布时间】:2011-10-06 18:47:42
【问题描述】:

我正在使用this link 的示例按照存储库和工作单元模式更新 SQL Server 2008 中的数据库表。

虽然我已经让插入工作。我很难让更新和删除工作。更新没有错误,也不会更新。删除会给出这样的 InvalidOperationException The object cannot be deleted because it was not found in the ObjectStateManager.

对于插入和删除,我使用示例中给出的 IObjectSet 方法。对于更新,我使用了 IObjectSet.Attach(entity) 方法,我将修改后的对象发送到该方法。

以下存储库和工作单元类的代码:

存储库类

命名空间数据访问 {

public interface IGenericRepository<T>
    where T : class
{
    void AddRow(T entity);
    void UpdateRow(T entity);
    void Delete(T entity);
}


public abstract class GenericRepository<T> : IGenericRepository<T>
        where T : class
{


    protected IObjectSet<T> _objectSet;

    public GenericRepository(ObjectContext Context)
    {
        _objectSet = Context.CreateObjectSet<T>();

    }




        public void AddRow(T entity)
        {
            _objectSet.AddObject(entity);
        }

        public void UpdateRow(T entity)
        {
            _objectSet.Attach(entity);
        }

        public void Delete(T entity)
        {
            _objectSet.DeleteObject(entity);
        }

   }
} 

工作单元类

namespace DataAccess 
{
    public interface IUnitOfWork
    {
        IGenericRepository<User> Users { get; }
        void Commit();
    }


    public class UnitOfWork : IUnitOfWork
    {

        private readonly ObjectContext _context;
        private UserRepository _userRepository;

        public UnitOfWork(ObjectContext Context)
        {

            if (Context == null)
            {
                throw new ArgumentNullException("Context wasn't supplied");
            }
            _context = Context;
        }



        public void Commit()
        {
            _context.SaveChanges();
        }

            public IGenericRepository<User> Users
            {
                get 
                {
                    if (_userRepository == null)
                    {
                        _userRepository = new UserRepository(_context);
                    }

                    return _userRepository;
                }
            }
    }
}

最后这就是我在调用代码中使用它进行更新的方式

public void UpdateUser(UserData userData)
{
   using (mEntities context = new mEntities())
   {
     UnitOfWork uow = new UnitOfWork(context);
     User usr = new User(); //This is the Entity Framework class
     usr.ID = userData.RowID;
     usr.UserName = userData.Username;   //usr.UserName is the primary key in the table

     uow.Users.UpdateRow(usr);
     uow.Commit();
   }
}

但是更新没有发生。我在这里做错了什么?我正在使用带有 EF 4 的 VS2010

感谢您的宝贵时间...

【问题讨论】:

    标签: c# entity-framework domain-driven-design repository-pattern unit-of-work


    【解决方案1】:

    UpdateRow 中附加项目后,您需要将其标记为已修改。实体以未更改状态附加。但是,要修改状态,您需要访问ObjectStateManager,它是上下文的一个属性。在 EF 4.1 I was told 中有一个方法 Entry() 在上下文中允许您设置状态。

    要删除一个实体,它必须存在于上下文中。如果尚未加载,则必须在删除之前附加它。

    还要注意difference 在使用new()CreateObject&lt;T&gt;() 之间。

    【讨论】:

    • 将我的存储库删除方法更改为现在读取为 ... _objectSet.Attach(entity); _context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Deleted); _objectSet.DeleteObject(entity);
    • 而且报错信息是一样的,是在哪里抛出的?当您可以设置对象的状态时,我假设它稍后也会找到该对象。更新至少有效吗?
    • 我通过对工作单元类和存储库类以及我在调用代码中使用它的方式进行一些小的修改来使其工作。彻底验证它为时已晚。 . 会在我回家时检查并报告。感谢您的提示。它开辟了解决这个问题的新方法..
    • 很高兴听到,如果您发布您的解决方案,我会很感兴趣。关于 EF 最让我恼火的是,感觉它应该工作的代码却经常不工作。
    • 当然,如果它通过我的测试,我会发布它:) .. 我同意 EF 刺激位。开发人员不必告诉 EF ObjectState 是否已更改。它应该足够聪明,已经知道这一点。接下来我正在考虑 NHibernate 或 BLToolkit。你对那些 ORM 有什么经验吗?
    【解决方案2】:

    所以可行的方法是更改​​通用存储库类中的更新方法

    public void UpdateRow(T entity)
    {
        _objectSet.Attach(entity);
        _context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
        _context.SaveChanges();
    }
    

    UnitOfWork 类不再需要 Commit() 方法。所以现在我的调用代码就是这样做的..

    public void UpdateUser(UserData userData)
    {
       using (mEntities context = new mEntities())
       {
         UnitOfWork uow = new UnitOfWork(context);
         User usr = new User(); //This is the Entity Framework class
         usr.ID = userData.RowID;
         usr.UserName = userData.Username;   //usr.UserName is the primary key in the table
    
         uow.Users.UpdateRow(usr);
         //uow.Commit();
       }
    }
    

    希望这对其他人有所帮助。虽然我没有彻底测试过这个,但我认为这应该适用于大多数情况。

    【讨论】:

      猜你喜欢
      • 2023-01-24
      • 2011-04-24
      • 1970-01-01
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-22
      • 1970-01-01
      相关资源
      最近更新 更多