gpt4 book ai didi

c# - 使用 Entity Framework 更新带有子集合的对象导致数据库中出现重复项

转载 作者:太空宇宙 更新时间:2023-11-03 21:07:04 24 4
gpt4 key购买 nike

我有一个 Customer 类,它与 Address 类有关系:

public class Customer
{
public int Id { get; set; }

public string Name { get; set; }

public virtual ICollection<Address> Addresses { get; set; }
}

public class Address
{
public int Id { get; set; }

public string Street1 { get; set; }

//Snip a bunch of properties

public virtual Customer Customer { get; set; }
}

我有一个编辑表单,其中显示了客户和地址的所有字段。提交此表单时,它会调用 Controller 中的 Edit 方法:

public ActionResult Save(Customer customer)
{
if (!ModelState.IsValid)
{
var viewModel = new CustomerFormViewModel
{
Customer = customer,
CustomerTypes = _context.CustomerTypes.ToList()
};

return View("CustomerForm", viewModel);
}

if (customer.Id == 0)
_context.Customers.Add(customer);
else
{
var existingCustomer = _context.Customers
.Include(c => c.Addresses)
.Single(c => c.Id == customer.Id);

existingCustomer.Name = customer.Name;
existingCustomer.TaxId = customer.TaxId;
existingCustomer.CustomerTypeId = customer.CustomerTypeId;
existingCustomer.CreditLimit = customer.CreditLimit;
existingCustomer.Exempt = customer.Exempt;
existingCustomer.Addresses = customer.Addresses;
}

_context.SaveChanges();

return RedirectToAction("Index", "Customers");
}

这不起作用,会在数据库的 Addresses 表中创建重复的条目。我想我明白为什么(EF 不够聪明,无法知道需要根据情况添加/修改/删除集合中的地址)。那么,解决此问题的最佳方法是什么?

我的直觉是我需要遍历 Addresses 集合并手动比较它们,从表单中添加客户不存在的任何新地址,更新存在的地址,以及删除那些不是由表单发送但存在于数据库中的客户。类似的东西(暂时忽略删除功能):

foreach(Address address in customer.Addresses)
{
if (address.Id == 0)
// Add record
else
// Fetch address record from DB
// Update data
}
// Save context

这是解决此问题的最佳方法,还是有任何 EF 技巧可以将子集合迭代并同步到数据库?

哦,还有一个让我摸不着头脑的问题 - 我可以理解如何在数据库中创建新的地址记录,但我不明白的是现有地址记录也已更新以使其具有customer_id 设置为 NULL...这到底是怎么发生的?这让我相信 EF 确实看到原始地址记录以某种方式链接(因为它正在修改它)但它不够聪明,无法意识到我传递的记录应该替换它?

谢谢——此外,这是 EF6 和 MVC5

最佳答案

问题出在线路上

     existingCustomer.Addresses = customer.Addresses;

在您的代码中。这就像从来自模型的 customer 分配字段 Addresses 。到目前为止没问题。关键是 customer 此时与数据库模型没有任何关系(它不是来自数据库而是来自 View )。

如果您想使用来自模型的数据更新 existingCustomer.Addresses,您需要合并数据而不是替换它。以下“伪代码”可能会给您指明方向:

void MergeAddresses(var existingAddresses, var newAddresses) {
foreach(var address in newAddresses) {
if (existingAddresses.Contains(newAddress)) {
// merge fields if applicable
}
else {
// add field to existingAddresses - be ware to use a "cloned" list
}
}
// now delete items from existing list
foreach (var address in existingAddresses.CloneList()) {
if (!newAddresses.Contains(address)) {
// remove from existingAddresses
}
}
}

关于c# - 使用 Entity Framework 更新带有子集合的对象导致数据库中出现重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40536008/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com