【问题标题】:Attach entity in modified state without marking all properties dirty以修改状态附加实体而不将所有属性标记为脏
【发布时间】:2011-07-26 12:25:20
【问题描述】:

我试图弄清楚如何将分离实体的特定属性标记为已修改。如果我执行以下操作,它将标记所有属性已修改,并且生成的 sql 将更新所有列。

/// <summary>
/// Sets the entity in the modified state.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">The entity.</param>
void IDbContext.Modified<T>(T entity)
{
    DbEntityEntry<T> entry = Entry(entity);
    if (entry.State == EntityState.Modified)
    {
        // if the state is already Modified we don't need to do anything else
        return;
    }

    if (entry.State == EntityState.Detached)
    {
        Set<T>().Attach(entity);

        //TODO: set specific properties modified instead of the the whole object.
        entry.State = EntityState.Modified;
    }
}

如何将仅更改的属性设置为已修改?

我正在尝试在实现DbContext 的类中使用它,该类将由通用存储库使用。目标是自动确定哪些属性与数据库值相比发生了更改,然后将这些更改的属性状态设置为已修改。在我当前的实现中,Modified 方法不知道实体类型,所以我不能简单地用context.Set&lt;T&gt;.Find(key) 检索它。

我想我可以添加一个接受 originalEntity 参数的重载,但如果可能的话我宁愿不这样做。

void IDbContext.Modified<T>(T entity, T originalEntity)
{
    DbEntityEntry<T> entry = Entry(entity);
    if (entry.State == EntityState.Modified)
    {
        // if the state is already Modified we don't need to do anything else
        return;
    }

    if (entry.State == EntityState.Detached)
    {
        Set<T>().Attach(entity);

        entry.OriginalValues.SetValues(originalEntity);
    }
}

【问题讨论】:

    标签: entity-framework entity-framework-4.1 ef-code-first


    【解决方案1】:

    您必须通过调用手动为每个属性执行此操作:

    DbEntityEntry<T> entry = context.Entry(entity);
    if (entry.State == EntityState.Detached)
    {
        context.Set<T>().Attach(entity);
        entry.Property(e => e.SomeProperty).IsModified = true;
        // TODO other properties
    }
    

    编辑:

    前面的示例假设您不想从数据库中重新加载实体,在这种情况下,您必须知道哪些属性已更改 - 由您来实现它。

    如果您对额外的数据库查询感到满意,您可以使用:

    var persistedEntity = context.Set<T>.Find(key);
    var entry = context.Entry(persistedEntity);
    entry.CurrentValues.SetValues(entity);
    

    编辑2:

    设置原始值应该是反向操作(但我没试过这个):

    var persistedEntity = context.Set<T>.Find(key);
    context.Entry(persistedEntity).State = EntityState.Detached;
    
    var entry = context.Entry(entity);
    context.Set<T>.Attach(entity);
    // I'm not sure if you have to change the state of the entity
    entry.OriginalValues.SetValues(persistedEntity);
    

    【讨论】:

    • 如何确定修改了哪些属性?我可以从数据库中检索当前值并让状态管理器解决吗?
    • @Ladislav:问题指出所有属性都被标记为已修改。您正在展示如何将单个属性标记为已修改,这在此处是多余的。
    • @Scott:我知道 OP 不想将所有属性都标记为已修改。
    • @Ladislav:我认为您回答的关键不是直接设置实体的状态(如在问题中),而是通过已更改的属性。
    • @Scott:如果是这样,答案是:对分离实体进行更改时不可能,因为上下文不知道它们。仅适用于附加/跟踪的实体,并且在您更改属性后自动完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    相关资源
    最近更新 更多