在修改状态下连接实体,而不会使所有属性脏污 [英] Attach entity in modified state without marking all properties dirty

查看:187
本文介绍了在修改状态下连接实体,而不会使所有属性脏污的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  ///<总结> 
///将实体设置为已修改状态。
///< / summary>
///< typeparam name =T>< / typeparam>
///< param name =entity>实体< / param>
void IDbContext.Modified< T>(T entity)
{
DbEntityEntry< T> entry = Entry(entity);
if(entry.State == EntityState.Modified)
{
//如果状态已经被修改,我们不需要执行任何其他操作
return;
}

if(entry.State == EntityState.Detached)
{
Set< T>()。

// TODO:设置特定属性而不是整个对象。
entry.State = EntityState.Modified;
}
}

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

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



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

  void IDbContext.Modified< T>(T entity,T originalEntity)
{
DbEntityEntry&T ; entry = Entry(entity);
if(entry.State == EntityState.Modified)
{
//如果状态已经被修改,我们不需要执行任何其他操作
return;
}

if(entry.State == EntityState.Detached)
{
Set< T>()。

entry.OriginalValues.SetValues(originalEntity);
}
}


解决方案

你必须通过调用以下方式手动执行每个属性:

  DbEntityEntry< T> entry = context.Entry(entity); 
if(entry.State == EntityState.Detached)
{
context.Set< T>()。
entry.Property(e => e.SomeProperty).IsModified = true;
// TODO其他属性
}

编辑:



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



如果您对数据库的其他查询感到满意,可以使用以下内容:

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

Edit2:



设置原始值应该反向操作(但我从未尝试过):

  var persistedEntity = context.Set< T> .Find(key) ; 
context.Entry(persistedEntity).State = EntityState.Detached;

var entry = context.Entry(entity);
context.Set< T> .Attach(entity);
//我不知道你是否必须更改实体的状态
entry.OriginalValues.SetValues(persistedEntity);


I'm trying to figure out how to mark specific properties of a detached entity as modified. If I do the following, it will mark all properties modified and the generated sql will update all columns.

/// <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;
    }
}

How do I set only changed properties as Modified?

I'm trying to use this in a class that implements DbContext that will be used by a generic repository. The goal is to automagically determine which properties have changed compared to the database values and then set those changed properties states to Modified. In my current implementation, the Modified method has no knowledge of the entity type, so I can't simply retrieve it with context.Set<T>.Find(key).

I suppose I could add an overload that accepts an originalEntity parameter, but I'd rather not if possible.

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);
    }
}

解决方案

You must do it for each property manually by calling:

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
}

Edit:

Former example suppose that you don't want to reload the entity from the database and in such case you must know which properties are changed - it is up to you to implement it.

If you are happy with additional query to database you can use this:

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

Edit2:

Setting original values should be reverse operation (but I have never tried this):

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);

这篇关于在修改状态下连接实体,而不会使所有属性脏污的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆