在通用EF核心存储库中出错



虽然我觉得这个问题应该已经回答了很多次,但我找不到任何有用的东西(除了我想避免的BulkInsert插件(

public virtual void AddRange(ICollection<T> entries)
{
_context.Set<T>().AddRange(entries);
}
public virtual void UpdateRange(ICollection<T> entries)
{
_context.Set<T>().UpdateRange(entries);
}

那么如何将这两种方法结合在一起呢?T是一个类,并且具有一个键"0";Id";属性(或者它可以有其他复合键,因此我希望这个解决方案是真正通用的(,但我不想用它来创建接口(检查是否等于0以将条目标记为已添加,否则为已修改(,因为它会使设计复杂化。

由于您想要执行"BulkInsert",因此可以使用DbContext提供的UpdateRange(IEnumerable items)方法。因此,在您的情况下,您将在存储库中创建一个新方法,并执行以下操作:

public void Upsert<T>(IEnumerable<T> items)
{
_context.DbSet<T>.UpdateRange(items);
_context.SaveChanges(); // persist to db
}

然后你可以像这样使用它(伪代码(

var myRepository = new repository<Onion>(_context);
var entities = _context.Onions;
foreach(var entity in entities){
entity.Layers = 8
}
myRepository.Upsert(entities);
// you could do SaveChanges() here too.

如果你想做一些自定义的事情,你可以使用以下方法,但它不如UpdateRange有效,因为它会对传入的集合中的每个项目进行查询。

public void AddOrUpdateRange<T>(ICollection<T> items)
{
foreach (var item in items)
{
var existingItem = _context.Set<T>().Find(item.Id);
if (existingItem != null)
{
_context.Entry(existingItem).CurrentValues.SetValues(item);
}
else
{
_context.Set<T>().Add(item);
}
}
_context.SaveChanges();
}

所有精彩的对话/评论。我也有类似的Upsert操作场景,但我必须让我的回购来处理。我试图修改它以满足您的需求,结果如下所示。

// Business layer
public async Task<bool> UpsertOnions(IEnumerable<Onions> list)
{
var existingRecs = (await _onionRepo.Get(existing => list.Select(model => model.Pk).Contains(existing.Pk)).ToList();
if (!existingRecs.Any())
return await _onionRepo.UpdateRange(existingRecs);

var allNetNew = list.Except(existingRecs);
return await _onionRepo.AddRange(allNetNew);
}
// Repo implementation
public async Task<bool> UpdateRange(IEnumerable<T> list)
{
_dbSet.UpdateRange(list);
// manage to handle your own here like return values etc. 
// call SaveChanges()
return true; // change to your own implementation
}
public async Task<bool> AddRange(IEnumerable<T> list)
{
_dbSet.AddRange(list);
// manage to handle your own here like return values etc. 
// call SaveChanges()
return true; // change to your own implementation
}

在这里,我的假设是,当您获得数据并映射到所需的数据模型时,具有自己openId的外部数据应该与模型的Pk字段相关联。

我也试图在没有特定数据库提供商的情况下谈论一般方面。比如Postgres或SQL,其中您的数据模型只会将您的Pk属性装饰为[Key]

相关内容

最新更新