c# - 在 LINQ for EF 中保存具有链接属性的新实体时不创建新实例
问题描述
我注意到,当我存储具有另一种类型的属性的对象时,它会被保存,但链接的属性也是如此。当两者都是新的或都在更新时,这有点整洁。
class Customer
{
public Guid Id { get; set; }
public List<Category> Categories { get; set; } ...
}
class Category
{
public Guid Id { get; set; }
public string Name { get; set; } ...
}
但是,当我创建一个新的客户实例但链接到一个预先存在的类别时,它变得有点不合适。在这种情况下,类别就像一个标签,所以几个客户将共享一个指向它的指针,每个新客户只需要重用已经存在的类别。(如果类别的 ID 设置为唯一,我会收到已创建对象的错误,如果不是,我会收到重复。)
我知道它与 EF 引擎相关的对象状态有关。它根本不知道新客户中的类别已经存在于数据库中,因此试图创建它。
我玩弄了这个状态并进入了一些复杂的算法,这在某种程度上影响了可读性。然后,我想出了以下方法。我实际上并没有对数据做任何事情——我只是将它拉入 EF 的客户端,让它知道它们的存在。
List<Guid> ids = data.Categories
.Select(_ => _.Id).ToList();
List<Category> existing = Context.Categories
.Where(_ => ids.Contains(_.Id)).ToList();
为了简单起见,让我们假设类别的数量是有限的,因此将检索重新编写为下面的代码。(基本上就像在说“嗯……说到类别……好吧,没关系。 ”,这在学术上似乎是错误的。)
List<Categories> _ = Context.Categories.ToList();
在这种情况下,是否有推荐最佳实践的模式或方法?
我意识到上面的示例只是 Q&D 解决方法。提到的实体状态很复杂。我觉得有一种巧妙的方法可以解决它。
解决方案
您不需要将所有现有类别加载到内存中。相反,只需通过从上下文加载新客户与他拥有的现有类别相关联。
Guid[] categoryIdsOfNewCustomer; // passed as part of the create command
var newCustomer = new Customer();
newCustomer.Categories = Context.Categories
.Where(c => categoryIdsOfNewCustomer.Contains(c.Id))
.ToList();
Context.Customers.Add(newCustomer);
Context.SaveChanges();
推荐阅读
- mongodb - MongoDb Where 子句中的嵌套查询
- javascript - 将一个数组的元素过滤到js中的另一个数组
- node.js - MongoDB Atlas 是否提供离线支持?
- javascript - 如何在html的弹出框中打印flask函数的输出?
- android - 对话框显示后如何从 RecyclerView 恢复刷过的项目?
- javascript - 我如何在 react-native 中使用条件运算符?发生此错误
- javascript - axios拦截器刷新token
- python - 构建 rom 枚举列表时出现意外的字典行为
- python - 我收到一个 discord.py 错误,说 AttributeError: 'str' object has no attribute 'read'
- css - 浮动子项与父窗口折叠