更新行如果存在其他插入逻辑与实体框架

Jon*_*ood 166 c# entity-framework

有没有人建议使用实体框架实现"更新行,如果它存在其他插入"逻辑的最有效方法?

Lad*_*nka 159

如果您正在使用附加对象(从上下文的同一实例加载的对象),您只需使用:

if (context.ObjectStateManager.GetObjectStateEntry(myEntity).State == EntityState.Detached)
{
    context.MyEntities.AddObject(myEntity);
}

// Attached object tracks modifications automatically

context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

如果您可以使用有关对象密钥的任何知识,您可以使用以下内容:

if (myEntity.Id != 0)
{
    context.MyEntities.Attach(myEntity);
    context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified);
}
else
{
    context.MyEntities.AddObject(myEntity);
}

context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

如果您无法通过其Id确定对象的存在,则必须执行查询查询:

var id = myEntity.Id;
if (context.MyEntities.Any(e => e.Id == id))
{
    context.MyEntities.Attach(myEntity);
    context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified);
}
else
{
    context.MyEntities.AddObject(myEntity);
}

context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)


Erk*_* M. 32

从Entity Framework 4.3开始,AddOrUpdate命名空间中有一个方法System.Data.Entity.Migrations:

public static void AddOrUpdate<TEntity>(
    this IDbSet<TEntity> set,
    params TEntity[] entities
)
where TEntity : class
Run Code Online (Sandbox Code Playgroud)

doc提供:

调用SaveChanges时,按键添加或更新实体.相当于数据库术语的"upsert"操作.使用迁移为播种数据时,此方法非常有用.


要回答@ Smashing1978评论,我将粘贴@Colin提供的链接中的相关部分

AddOrUpdate的工作是确保在开发期间为数据设定种子时不创建重复项.

首先,它将在您的数据库中执行查询,查找记录,其中您作为键提供的任何内容(第一个参数)与AddOrUpdate中提供的映射列值(或多个值)相匹配.所以这对于匹配来说有点松散 - 但是对于播种设计时间数据来说非常好.

更重要的是,如果找到匹配项,则更新将全部更新并清除AddOrUpdate中没有的任何内容.

也就是说,我有一种情况,我从外部服务中提取数据,并通过主键插入或更新现有值(我的本地数据为消费者是只读的) - 现在已经AddOrUpdate在生产中使用超过6个月了远没有问题.

  • 请注意AddOrUpdate方法:http://thedatafarm.com/data-access/take-care-with-ef-4-3-addorupdate-method/ (9认同)
  • System.Data.Entity.Migrations命名空间包含与基于代码的迁移及其配置相关的类.是否有任何理由不在我们的存储库中使用此非迁移实体AddOrUpdates? (7认同)

cis*_*eat 8

如果您知道您使用相同的上下文而不是分离任何实体,则可以创建如下通用版本:

public void InsertOrUpdate<T>(T entity, DbContext db) where T : class
{
    if (db.Entry(entity).State == EntityState.Detached)
        db.Set<T>().Add(entity);

    // If an immediate save is needed, can be slow though
    // if iterating through many entities:
    db.SaveChanges(); 
}
Run Code Online (Sandbox Code Playgroud)

db 当然可以是一个类字段,或者可以将方法设为静态和扩展,但这是基础知识.


Sta*_*ked 8

召唤时会发生魔力,SaveChanges()并取决于当前的情况EntityState.如果实体有EntityState.Added,它将被添加到数据库中,如果它有EntityState.Modified,它将在数据库中更新.所以你可以实现InsertOrUpdate()如下方法:

public void InsertOrUpdate(Blog blog) 
{ 
    using (var context = new BloggingContext()) 
    { 
        context.Entry(blog).State = blog.BlogId == 0 ? 
                                   EntityState.Added : 
                                   EntityState.Modified; 

        context.SaveChanges(); 
    } 
}
Run Code Online (Sandbox Code Playgroud)

有关EntityState的更多信息

如果您无法检查Id = 0以确定它是否是新实体,请查看Ladislav Mrnka答案.


Ali*_*vuz 5

使用 Any 检查现有行。

public static void insertOrUpdateCustomer(Customer customer)
{
    using (var db = getDb())
    {

        db.Entry(customer).State = !db.Customer.Any(f => f.CustomerId == customer.CustomerId) ? EntityState.Added : EntityState.Modified;
        db.SaveChanges();

    }

}
Run Code Online (Sandbox Code Playgroud)