ASP.. NET MVC 5编辑动作-如何写入多个数据库表/模型

本文关键字:何写入 数据库 模型 MVC NET 编辑 ASP | 更新日期: 2023-09-27 18:02:00

是否有任何方法以某种方式组合来自两个模型的数据,然后将它们映射到编辑操作上下文中的相同viewModel ?

我从来没有在ASP的编辑动作一次更新几个表。. NET MVC与实体框架6.1.3。这是布局:

我有一个名为"地址"的DB表,其中包含StreetNumber, StreetName, City, State, ZipCode字段。它与另一个名为Bars的表具有一对一的关系。例如,一个栏只能有一个地址,一个地址只能有一个栏。

因为我将这些数据存储在两个单独的表中,所以我很难成功地实现从一个表单 (BarForm)获取数据的Edit操作,并且应该更新Bar和Address数据库表。查看我的代码:

BarController

public ActionResult Edit(int id)
        {
            var bar = _context.Bars.SingleOrDefault(m => m.Id == id);
            var address = _context.Addresses.SingleOrDefault(a => a.BarId == id);
            //Make sure that the id actually exists:
            if (bar == null)
            {
                return HttpNotFound();
            }
            var viewModel = Mapper.Map<Bar, BarFormViewModel>(bar, new BarFormViewModel());
            if (address == null)
            {
                address = new Address();
            }
            Mapper.Map<Address, BarFormViewModel>(address, viewModel);
            viewModel.IsNew = false;
            return View("BarForm", viewModel);
        }
        [ValidateAntiForgeryToken]
        public ActionResult Save(BarFormViewModel bar)
        {
            if (!ModelState.IsValid)
            {
                var viewModel = Mapper.Map<BarFormViewModel, BarFormViewModel>(bar, new BarFormViewModel());
                viewModel.IsNew = false;
                return View("BarForm", viewModel);
            }
            if (bar.Id == 0)
            {
                var newbar = Mapper.Map<BarFormViewModel, Bar>(bar);
                newbar.LastUpdated = DateTime.UtcNow;
                _context.Bars.Add(newbar);
                var addressToAdd = Mapper.Map<BarFormViewModel, Address>(bar);
                _context.Addresses.Add(addressToAdd);
            }
            else
            {
                var barInDb = _context.Bars.Single(b => b.Id == bar.Id);
                var addressInDb = _context.Addresses.Single(a => a.BarId == bar.Id);
                Mapper.Map<BarFormViewModel, Bar>(bar, barInDb);
                Mapper.Map<BarFormViewModel, Address>(bar, addressInDb);
            }
            _context.SaveChanges();
            return RedirectToAction("Index", "Bar");
        }

域模型:

public class Bar
    {
        public int Id { 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; }
        [Display(Name = "Last Updated")]
        public DateTime LastUpdated { get; set; }
    }
 public class Address
    {
        public int Id { get; set; }
        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 Bar Bar { get; set; }
        public int BarId { get; set; }
    }

视图模型,包括地址和栏属性:

{
    public class BarFormViewModel
    {
        public int? Id { get; set; }
        public string Name { get; set; }
        [Required]
        [Display(Name = "Google Place ID")]
        public string GooglePlaceId { get; set; }
        [Display(Name = "Sunday Happy Hour Info:")]
        public string SundayDiscounts { get; set; }
        [Display(Name = "Monday Happy Hour Info:")]
        public string MondayDiscounts { get; set; }
        [Display(Name = "Tuesday Happy Hour Info:")]
        public string TuesdayDiscounts { get; set; }
        [Display(Name = "Wednesday Happy Hour Info:")]
        public string WednesdayDiscounts { get; set; }
        [Display(Name = "Thursday Happy Hour Info:")]
        public string ThursdayDiscounts { get; set; }
        [Display(Name = "Friday Happy Hour Info:")]
        public string FridayDiscounts { get; set; }
        [Display(Name = "Saturday Happy Hour Info:")]
        public string SaturdayDiscounts { get; set; }
        [Display(Name = "Last Updated")]
        public DateTime? LastUpdated { get; set; }

        //Address Model Info
        public Address Address { get; set; }
        public int? AddressId { get; set; }
        [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 bool IsNew { get; set; }
    }

这里的问题是,我得到一个空AddressId与此设置,这是导致一个异常,当保存操作得到运行。这是因为BarForm视图被传递了一个ViewModel,这个ViewModel是从一个Bar对象映射过来的,而Bar域模型实际上没有地址信息,因为它不是地址模型/表。

是否有任何方法以某种方式组合来自地址和栏模型的数据,然后将它们映射到相同的viewModel?

我一直得到一个序列不包含任何元素错误为这一行在保存操作:

var addressInDb = _context.Addresses.Single(a => a.Id == bar.AddressId);

我也试过:

var addressInDb = _context.Addresses.Single(a => a.BarId == bar.Id);

既不工作。我明白错误在说什么,也检查了我隐藏的Addressid字段的实际HTML,它是空白的…查看我的BarForm视图中的代码:

 @Html.HiddenFor(m => m.Id)
    @Html.HiddenFor(m => m.AddressId)
    @Html.AntiForgeryToken()

ASP.. NET MVC 5编辑动作-如何写入多个数据库表/模型

删除new BarFormViewModel()作为映射调用中的第二个参数,因为它是不必要的。

在post操作中,在if语句中检查ModelState是否有效。Id == 0, bar已经是视图模型,所以不需要映射。

当您创建您的AutoMapper映射时,您必须创建一个自定义属性映射,因为Address。Id属性不会自动映射到AddressId属性,因为名称不相同。

AutoMapper.Mapper.CreateMap<Address, BarFormViewModel>()
.ForMember(dest => dest.AddressId, o => o.MapFrom(source => source.Id));

然后对逆映射做同样的处理。