【发布时间】:2022-12-10 09:52:27
【问题描述】:
虽然感觉这个问题应该已经回答了很多次,但我找不到任何有用的东西(除了我想避免的 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 是一个类并且有一个键“Id”属性(或者它可以有其他复合键,因此我希望这个解决方案是真正通用的),但我不想从中创建一个接口(检查是否等于到 0 以将条目标记为已添加,否则已修改),因为它会使设计复杂化。
【问题讨论】:
-
DbSet 已经是一个通用的单一实体存储库。 DbContext 已经是一个多实体存储库和工作统一体。除非您想覆盖现有行为,否则您不会明确告诉 EF Core 分离的对象是新的还是修改过的。 ORM 旨在给人一种使用内存中对象而不是表和行的印象。其中最先进的不需要“upsert”——这甚至不是存储库模式,它是更原始的数据访问对象模式
-
Add/AddRange和Update/UpdateAsync都没有向数据库写入任何内容。他们在特定状态下附加一个分离的实体。如果实体具有数据库生成的密钥,Update 将开始跟踪具有处于修改状态的密钥和没有处于已添加状态的密钥的实体。无需调用Add/AddRange,除非应用程序想要使用客户端生成的密钥附加新实体。调用SaveChanges时将保存所有更改 -
if equals to 0 to mark entry as Added, Modified otherwiseEF 已经这样做了 -
You don't to tell EF Core explicitly whether a detached object is new or modified- 好的,让我们考虑一下:我有一个名为 Onion 的表。我有一份要插入到这张桌子上的洋葱清单。其中一些已经存在于数据库中——我必须为这些调用更新。其中一些是新的 - 我必须为这些调用添加。如何让 EF 自行决定是调用 Update 还是 Insert 而不是手动调用? -
那是错误的心智模型。您将 EF 视为数据访问对象或数据库连接。 EF Core 已经提供了您所要求的内容。我已经发布了解释 EF 如何决定的文档的链接在什么状态下跟踪对象- 不是调用什么方法。您可以对新对象和修改后的对象使用
Update。如果键是数据库生成的,则没有键值的对象被认为是新的。具有键值的对象被认为已修改
标签: c# .net generics entity-framework-core upsert