实体框架一对一关系表单编辑/保存
本文关键字:编辑 保存 表单 关系 框架 一对一 实体 | 更新日期: 2023-09-27 18:02:26
- 我有一个名为Bar的域类,它有很多属性
- Bar的属性之一实际上是另一个名为Address的域类,其类型为Address
- Address与Bar之间存在一对一关系。所以一个酒吧有一个地址,一个地址有一个酒吧
- 因此,我将这两个域类都设置为使用BarId作为它们的主键
-
根据Microsoft Virtual Academy讲师的说法,为了让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同样,我可以从数据库中选择一个Address对象并将其传递到我的表单(通过视图模型(,或我可以只选择一个栏,然后传递我的视图栏。住址做这两件事有什么区别吗?到目前为止,我的表单可以工作,但通过视图模型传递到表单中并返回的数据实际上并没有保存到数据库中。所有而非传递到视图模型并通过表单的数据都保存得很好。以下是我的编辑和保存操作供参考:
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");
}
我看了一下这个问题,但这似乎不是一个问题。
当前数据库设计缺少的是database normalization rules
上First Normal Form
中的Identify each set of related data with a primary key
(请选中此处(。如果你有一个主键,为什么不把它们做成一个表呢?它将更快、更容易维护。
但我认为Bar
和Address
本质上是不同的,所以最好有两个主键不同的表。然后将BarId
添加到Address
表,将public virtual Address Address
添加到Bar
表。因此,您将有一个主Bar
对象和关联的Address
对象。
然后Entity Framework
将完成其余工作!:如果您当前的酒吧没有当前的Address对象,它会创建它,如果您更改酒吧上的相关地址详细信息并尝试更新酒吧,EF也会更新Address。
还请查看此处,了解EF如何处理相关对象。