Entity Framework 如何正确地使用 Code First 更新实体?

4

我在通用仓库中有以下更新方法

public class Repository<T> : IRepository<T> where T : class
{
    private readonly DbSet<T> _dbSet;
    public virtual T Update(T item) {
        return _dbSet.Attach(item);
    }
}

UnitOfWork有一个提交方法,该方法调用上下文中的SaveChanges。更多详细信息请参见此处:
https://codereview.stackexchange.com/questions/19037/entity-framework-generic-repository-pattern

当我更新一个实体并调用时:

ProductRepository.Update(modifiedProduct);
UnitOfWork.Commit;

没有任何东西会流向数据库。

然而,仅仅调用Commit就可以工作(不需要调用update方法)。

那么,Attach方法到底在做什么,导致更改无法流向数据库呢?我认为在Update方法中调用Attach方法是正确的。那么是什么导致了意外的行为呢?

从CodePlex上的EF源代码来看。

/// <summary>
///     Attaches the given entity to the context underlying the set.  That is, the entity is placed
///     into the context in the Unchanged state, just as if it had been read from the database.
/// </summary>
/// <param name="entity"> The entity to attach. </param>
/// <returns> The entity. </returns>
/// <remarks>
///     Attach is used to repopulate a context with an entity that is known to already exist in the database.
///     SaveChanges will therefore not attempt to insert an attached entity into the database because
///     it is assumed to already be there.
///     Note that entities that are already in the context in some other state will have their state set
///     to Unchanged.  Attach is a no-op if the entity is already in the context in the Unchanged state.
/// </remarks>
public object Attach(object entity)
{
    Check.NotNull(entity, "entity");

    InternalSet.Attach(entity);
    return entity;
}
2个回答

5
///     Attach is used to repopulate a context with an entity that is known to already exist in the database.
///     SaveChanges will therefore not attempt to insert an attached entity into the database because
///     it is assumed to already be there.
///     Note that entities that are already in the context in some other state will have their state set
///     to Unchanged. 

将实体附加后,状态将保持为"未更改(Unchanged)",因此不会为该实体触发任何UPDATE SQL语句。您需要手动设置实体的状态。


所以我需要将EntityState设置为Modified,但我的问题是当前我的Repository对Context一无所知。有什么解决方法吗? - ashutosh raina
我认为最好在存储库级别上实现。如果不这样做,您将无法使用 EF 的某些功能(隐藏)。 - Jayantha Lal Sirisena
是的,你的代码库应该有对上下文的引用,如果你希望在多个代码库中共享上下文,它可以作为一个依赖项。 - devdigital

4

在向数据库查询时,您需要将对象作为 modifiedadded 附加到查询中。

  public virtual T AttachAsModified(T item) {
        item = _dbSet.Attach(item);
        db.Entry(item).State = System.Data.EntityState.Modified
        return item;
    }

public virtual T AttachAsModified(T item) { db.Entry(item).State = System.Data.EntityState.Modified } 这段代码是可以正常工作的... 但是添加 _dbset.Attach(item) 就会出现问题... 我是否错误地理解了 Attach 方法? - ashutosh raina
在我们附加实体之后,需要设置状态。 - ashutosh raina

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