我的Customer
模型带有MailingAddress
属性 - 这是Address
类的导航属性:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Address MailingAddress { get; set; }
}
我有一个发布视图模型的表单,其中包含customer
以及邮寄地址。这是控制器中的save方法:
public ActionResult Save(CustomerFormViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View("CustomerForm", viewModel);
}
if (viewModel.Customer.Id == 0)
{
_context.Customers.Add(viewModel.Customer);
}
else
{
var customerInDb = _context.Customers
.Single(c => c.Id == viewModel.Customer.Id);
_context.Entry(customerInDb).CurrentValues.SetValues(viewModel.Customer);
}
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
发布新客户时,一切正常(大多数情况下,请参阅下面的说明),并创建客户以及相应的地址记录。但是,当我编辑现有条目时,客户会更新,但地址不会更新。我验证了更新的地址正在客户对象中传递。如果我添加这样一行:
_context.Entry(customerInDb.MailingAddress).CurrentValues.SetValues(viewModel.Customer.MailingAddress);
然后更新。
这里的孩子仍被视为独立实体吗?我假设因为它是Customer
的一个属性我正在获取它将自动与父节点一起保存。为什么这会使用新记录而不是更新?
关于新记录创建的一个注意事项 - 创建了Customer
记录,并且MailingAddress_Id
指向该地址。还创建了Address
记录,但其Customer_Id
为空...想法为什么EF不在关系的那一侧添加密钥?地址模型和视图模型代码,以防它有用:
public class Address
{
public int Id { get; set; }
public string Street1 { get; set; }
// Snip a bunch of address data properties
public virtual Customer Customer { get; set; }
}
public class CustomerFormViewModel
{
// Snip irrelevant properties
public Customer Customer { get; set; }
}
答案 0 :(得分:3)
首先,如果您的Customer
和Address
处于一对一关系中,则不需要外键。实际上,在一对一关系中,关系依赖方面的主键也是主方的外键。其次,当您创建新Customer
时,您使用context.Customers.Add(viewModel.Customer);
并添加模型及其所有子模型,但是当您尝试使用_context.Entry(customerInDb).CurrentValues.SetValues(viewModel.Customer);
进行更新时,它不会添加所有子导航属性,要这样做,你必须明确告诉EntityFramework:
var customerInDb = _context.Customers
.Single(c => c.Id == viewModel.Customer.Id);
_context.Entry(customerInDb)
.CurrentValues
.SetValues(viewModel.Customer);
var mailingAddressInDb = _context.Addresses
.Single(m => m.Id = viewModel.Customer.MailingAddress.Id);
_context.Entry(mailingAddressInDb)
.CurrentValues
.SetValues(viewModel.Customer.MailingAddress);
它应该适合你。但它有点尴尬。当你有几十个模型时,你甚至都不想想象它。
好消息是,有一个API可以从根本上解决这个问题。只需几步即可解决您的问题。您可以使用Install-Package Ma.EntityFramework.GraphManager
从NuGet安装它,配置模型以满足prerequisites(这非常简单)并使用单行代码处理整个图形:
public ActionResult Save(CustomerFormViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View("CustomerForm", viewModel);
}
// Define state of whole graph with single line
_context.AddOrUpdate(viewModel.Customer);
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
请快速浏览一下CodeProject article。它有示例代码,因此您可以下载并检查它。我是此API的所有者,我随时准备回答您的问题。