EF Core 中 AddorUpdate 的替代方法是什么?

问题描述 投票:0回答:4

我想使用 EF Core 实现通用存储库中的 ADDorUpdate() 方法,如下所示? 有人可以帮助我吗?

  public virtual void AddOrUpdate(T entity)
    {
        #region Argument Validation

        if (entity == null)
        {
            throw new ArgumentNullException("entity");
        }
        #endregion
         DbSet.AddOrUpdate(e => e.Id, entity);  
        this.DbContext.SaveChanges();
    }
c# asp.net-core generics entity-framework-core repository-pattern
4个回答
53
投票

简单使用

context.Update(entity);

它完全基于实体 PrimaryKey 的值

AddOrUpdate
(0 表示添加,> 0 表示更新):

public virtual void AddOrUpdate(T entity)
{
    if (entity == null)
        throw new ArgumentNullException("entity");

     this.DbContext.Update(entity);  
     this.DbContext.SaveChanges();
}

3
投票

如果您使用复合键,您可以使用我写的下一个方法:

public static void AddOrUpdateRange<TEntity>(this DbSet<TEntity> set, IEnumerable<TEntity> entities)
            where TEntity : class
        {
            foreach (var entity in entities)
            {
                _ = !set.Any(e => e == entity) ? set.Add(entity) : set.Update(entity);
            }
        }

0
投票

您可以检查该实体是否存在。 像这样:

book exists= context.Set<T>().Any(x=>x.Id==entity.Id);

像这样使用。

if(exists)
context.Set<T>().Add(entity);
else
context.Set<T>().Update(entity);

编辑: 由于这是一个通用方法,因此您应该对该方法创建一个约束才能使其正常工作。例如,抽象类。

public abstract class BaseEntity
{
public int Id {get; set; }
}

你的方法应该有这个约束。

public virtual void AddOrUpdate(T entity)
 where T: BaseEntity{}

您的实体应该继承自

BaseEntity


0
投票

EF Core(包含 6)不支持 AddOrUpdate 功能。实现它的一种方法是在数据库中创建upsert(插入或更新)函数,并在 EF 方法

ExecuteSqlRawAsync
的帮助下调用它。

这是一个使用 PostgreSQL 具有 upsert 函数的示例表

CREATE TABLE employee(
 id int PRIMARY KEY,
 "name" TEXT,
 "position" TEXT, 
 unique_identification_number int8 unique
);

CREATE OR REPLACE FUNCTION upsert_employee(_id int, _name TEXT,_position 
TEXT,_unique_identification_number int8)
   RETURNS void
   LANGUAGE plpgsql
   AS 
$$
BEGIN
   INSERT INTO employee(id,name,"position",unique_identification_number)
   VALUES(_id,_name,_position,_unique_identification_number)
   ON CONFLICT(unique_identification_number)
   DO UPDATE SET 
       name = EXCLUDED.name,
       "position" = EXCLUDED."position"
   WHERE employee.id = _id;
END;
$$;

在后端使用EF调用pg函数

ExecuteSqlRawAsync
:

var sql = @"SELECT upsert_employee(@p0,@p1,@p2,@p3)";
await _context.Database.ExecuteSqlRawAsync(sql, 1,'test','hr', 12);

当您的实体是分离的,您不使用自动增量 pk 并且您只想为数据库创建一个事务(例如,不要让实体检查它是否存在,然后决定创建)时,这种方法很有用或更新)。

缺点是它不通用。

© www.soinside.com 2019 - 2024. All rights reserved.