根据Microsoft Virtual Academy instructors,为了使EF能够理解这一点,您必须使用[Key]属性以及[ForeignKey]属性指定主键。他们还说你必须像我一样将属性类型声明为虚拟。看这里: 地址域模型:
public class Address
{
[RegularExpression("([1-9][0-9]*)", ErrorMessage = "Must be a number")]
public int? Number { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
public string State { get; set; }
[Required]
public int ZipCode { get; set; }
public virtual Bar Bar { get; set; }
[Key]
[ForeignKey("Bar")]
public int BarId { get; set; }
}
BAR域模型:
public class Bar
{
public int BarId { get; set; }
public string Name { get; set; }
[Required]
public string GooglePlaceId { get; set; }
public string SundayDiscounts { get; set; }
public string MondayDiscounts { get; set; }
public string TuesdayDiscounts { get; set; }
public string WednesdayDiscounts { get; set; }
public string ThursdayDiscounts { get; set; }
public string FridayDiscounts { get; set; }
public string SaturdayDiscounts { get; set; }
public virtual Address Address { get; set; }
[Display(Name = "Last Updated")]
public DateTime LastUpdated { get; set; }
最后但并非最不重要的是,这是我正在使用的视图模型:
{
public class BarFormViewModel
{
public Address Address { get; set; }
public Bar Bar { get; set; }
public bool IsNew { get; set; }
}
}
我的问题是,如何将其正确地实现到表单逻辑中,以便在编辑栏时可以编辑地址?我因为Bar域有一个地址而被抛弃意味着我可以告诉我的表单更新Address.StreetName或者我可以告诉我的表单更新Bar.Address.StreetName,其中Address.BarId == bar.BarId。同样,我可以选择一个从数据库中寻址对象并将其传递给我的表单(通过viewmodel),或我只能选择一个栏然后传递我的视图bar.Address。做这两件事有什么不同吗?到目前为止,我的表单工作,但通过viewmodel传递到表单和后面的数据实际上并没有保存到数据库中。 not 的所有数据都传递给viewmodel并通过表单保存得很好。 以下是我的编辑和保存操作供参考:
public ActionResult Edit(int id)
{
var bar = _context.Bars.SingleOrDefault(b => b.BarId == id);
//Make sure that the id actually exists:
if (bar == null)
{
return HttpNotFound();
}
var viewModel = new BarFormViewModel
{
Address = bar.Address,
Bar = bar,
IsNew = false
};
return View("BarForm", viewModel);
}
[ValidateAntiForgeryToken]
public ActionResult Save(Bar bar)
{
if (!ModelState.IsValid)
{
var viewModel = Mapper.Map<Bar, BarFormViewModel>(bar);
viewModel.IsNew = false;
return View("BarForm", viewModel);
}
if (bar.BarId == 0)
{
bar.LastUpdated = DateTime.UtcNow;
_context.Bars.Add(bar);
}
else
{
var barInDb = _context.Bars.Single(b => b.BarId == bar.BarId);
// var addressInDb = _context.Addresses.Single(a => a.BarId == bar.Bar.Address.BarId);
Mapper.Map(bar, barInDb);
barInDb.MondayDiscounts = bar.MondayDiscounts;
barInDb.LastUpdated = DateTime.UtcNow;
}
_context.SaveChanges();
return RedirectToAction("Index", "Bar");
}
我看过this question,但这似乎不是同一个问题。
答案 0 :(得分:0)
您当前数据库设计中遗漏的内容为Identify each set of related data with a primary key
First Normal Form
database normalization rules
(检查here)。如果你有一个主键,为什么不让它们只是一个表?它将更快更容易维护。
但我认为,因为Bar
和Address
本质上是不同的东西,所以最好有两个具有不同主键的表。然后将BarId
添加到Address
表,将public virtual Address Address
添加到Bar
表。因此,您将拥有一个主Bar
对象和关联的Address
对象。
然后Entity Framework
将完成其余操作!:如果您当前的Bar没有当前的Address对象,它会创建它,如果您更改了bar上的相关地址详细信息并尝试更新bar, EF也会更新地址。
请同时检查here以获取有关EF如何处理关联对象的一些建议。