实体框架一对一关系表单编辑/保存

时间:2016-08-14 22:45:53

标签: c# asp.net-mvc entity-framework

  • 我有一个名为Bar的域类,它有一堆属性
  • Bar所具有的其中一个属性实际上是另一个名为Address的域类,其类型为Address。
  • 地址与Bar有一对一关系。所以一个Bar有一个地址,一个地址有一个吧。
  • 由于这个原因,我将两个域类设置为使用BarId作为主键。
  • 根据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,但这似乎不是同一个问题。

1 个答案:

答案 0 :(得分:0)

您当前数据库设计中遗漏的内容为Identify each set of related data with a primary key First Normal Form database normalization rules(检查here)。如果你有一个主键,为什么不让它们只是一个表?它将更快更容易维护。

但我认为,因为BarAddress本质上是不同的东西,所以最好有两个具有不同主键的表。然后将BarId添加到Address表,将public virtual Address Address添加到Bar表。因此,您将拥有一个主Bar对象和关联的Address对象。

然后Entity Framework将完成其余操作!:如果您当前的Bar没有当前的Address对象,它会创建它,如果您更改了bar上的相关地址详细信息并尝试更新bar, EF也会更新地址。

请同时检查here以获取有关EF如何处理关联对象的一些建议。