使用Entity Framework Code First最有效地处理创建、更新和删除操作

29

注意: 我使用的是Entity Framework 5版本

在我的通用仓库中,我有以下AddEditDelete方法:

public class EntityRepository<T> : IEntityRepository<T>
    where T : class, IEntity, new() {

    readonly DbContext _entitiesContext;

    public EntityRepository(DbContext entitiesContext) {

        if (entitiesContext == null) {

            throw new ArgumentNullException("entitiesContext");
        }

        _entitiesContext = entitiesContext;
    }

    //...

    public virtual void Add(T entity) {

        DbEntityEntry dbEntityEntry = _entitiesContext.Entry<T>(entity);
        if (dbEntityEntry.State != EntityState.Detached) {

            dbEntityEntry.State = EntityState.Added;
        }
        else {

            _entitiesContext.Set<T>().Add(entity);
        }
    }

    public virtual void Edit(T entity) {

        DbEntityEntry dbEntityEntry = _entitiesContext.Entry<T>(entity);
        if (dbEntityEntry.State == EntityState.Detached) {

            _entitiesContext.Set<T>().Attach(entity);
        }

        dbEntityEntry.State = EntityState.Modified;
    }

    public virtual void Delete(T entity) {

        DbEntityEntry dbEntityEntry = _entitiesContext.Entry<T>(entity);
        if (dbEntityEntry.State != EntityState.Detached) {

            dbEntityEntry.State = EntityState.Deleted;
        }
        else {

            DbSet dbSet = _entitiesContext.Set<T>();
            dbSet.Attach(entity);
            dbSet.Remove(entity);
        }
    }
}

您认为这些方法是否实现得很好?特别是Add方法。将Add方法实现为下面这样是否更好呢?

public virtual void Add(T entity) {

    DbEntityEntry dbEntityEntry = _entitiesContext.Entry<T>(entity);
    if (dbEntityEntry.State == EntityState.Detached) {

        _entitiesContext.Set<T>().Attach(entity);
    }

    dbEntityEntry.State = EntityState.Added;
}

1
@CoffeeAddict 这是EF 5.0.0。无论是DB first还是Code first,在这里都不重要,因为它是一个通用的存储库代码。 - tugberk
你可以使用新发布的库,它将自动设置实体图中所有实体的状态。你可以阅读我对类似问题的回答 - Farhad Jabiyev
1个回答

37

对于添加:

public bool Add<E>(E entity) where E : class
        {
            DataContext.Entry(entity).State = System.Data.EntityState.Added;
            Save();
        }

更新:

 public bool Update<E>(E entity) where E : class
        {
            DataContext.Entry(entity).State = System.Data.EntityState.Modified;
            Save();
        }

删除操作:

 public bool Delete<E>(E entity) where E : class
        {
            DataContext.Entry(entity).State = System.Data.EntityState.Deleted;
            Save();
        }

还需要一个私有的Save()方法,该方法返回真或假,这样在控制器中就可以根据结果轻松地回退。

private bool Save()
        {
            return DataContext.SaveChanges() > 0;                
        }

这只是我通用仓储的一部分,在企业应用中非常有效。

更新:

Detach仅影响传递给该方法的特定对象。如果被分离的对象在对象上下文中具有相关对象,则这些对象不会被分离。

当设置实体的状态或调用SaveChanges()时,EF将自动附加图形中已分离的对象。

我真的不知道为什么需要从上下文中分离对象。您也可以使用AsNoTracking()从数据库加载实体,而不将它们首先附加到上下文中。


如果您传递到“Add”或“Edit”方法中的对象处于“Detached”状态,会发生什么? - tugberk
这是代替在DbContext或Repository中拥有IDbSet<T>属性吗? - IAbstract
where E : class 的目的是什么 - 不确定如何搜索以获取更多信息? - Cody
4
这是一个限制条件,因此类型参数必须是引用类型。http://msdn.microsoft.com/en-us/library/d5x73970.aspx - Matija Grcic
为什么需要类型参数? - Ian Warburton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接