AutoMapper展平是否适用于查看记录但不能创建/更新?

时间:2013-10-03 18:38:58

标签: asp.net-mvc entity-framework automapper

我有一个与地址模型具有一对一关系的公司模型。我正在为我的创建,细节,编辑和更新操作使用视图模型。我使用AutoMapper从模型映射到视图模型,反之亦然。

我的视图模型用于包含公开公司地址的属性:

public Address Address { get; set; }

我最近将其更改为抽象地址数据并对地址的某些属性进行验证(有关详情,请参阅我的related question here ...)

在这些变化之后,我有了以下属性:

public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
// etc...

这打破了我的AutoMapper。根据我的另一个问题的答案,我决定使用AutoMapper的展平功能。我更改了我的属性名称以匹配Navigation_propertyProperty的命名约定:

public string AddressAddress1 { get; set; }
public string AddressAddress2 { get; set; }
public string AddressCity { get; set; }
// etc...

我修改了我的视图以使用这些新的属性名称,并且它有效!好吧,有点。如果我查看公司的详细信息,我可以看到它的地址。如果我删除公司,则该地址也会被成功删除。但是,在编辑时,我更改的公司属性会被保存,但地址属性则不会。如果我创建一家新公司,则会创建一个没有地址的公司。

所以似乎AutoMapper正在运行(它能够为现有公司提取地址)但更新并没有进入数据库...如果我手动将视图模型属性映射到company.Address属性,它可以工作,但我无法弄清楚如何使用AutoMapper。

我是否需要通过告知上下文专门更新地址或其他内容来更改我在控制器中保存数据的方式?

这是我的控制器的编辑方法供参考:

public ActionResult Edit(int id = 0)
{
    Company company = db.Companies
        .Include(c => c.Address)
        .Where(c => c.CompanyID == id)
        .Single();

    // Make sure we found something
    if (company == null)
        return HttpNotFound();

    // Use AutoMapper to map model to viewmodel
    CompanyViewModel viewModel = Mapper.Map<Company, CompanyViewModel>(company);

    return View(viewModel);
}


[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CompanyViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        // Find appropriate record in DB
        Company company = db.Companies
            .Include(c => c.Address)
            .Where(c => c.CompanyID == viewModel.CompanyID)
            .Single();

        // Map viewmodel data to company object
        Mapper.Map<CompanyViewModel, Company>(viewModel, company);

        // I've also tried the following without success:
        // Mapper.Map(viewModel, company);
        // company = Mapper.Map<CompanyViewModel, Company>(viewModel, company);

        // Save and redirect to company list
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(viewModel);
}

感谢任何帮助。如上所述,我总是可以手动从视图模型映射到要更新/创建的对象(事实上,有些人会认为这是一种更好的写入数据库的做法)但我很好奇为什么映射在一个方向上工作只有...如果您需要更多代码,请告诉我......

1 个答案:

答案 0 :(得分:2)

老实说,我不确定为什么只在某些情况下不会起作用,现在你已经改变了一切,我讨厌告诉你撤消它,但在这种情况下,通常更容易定制您的地图:

AutoMapper.Mapper.CreateMap<Company, CompanyViewModel>()
    .ForMember(dest => dest.Address1, opts => opts.MapFrom(src => src.Address.Address1))
    .ForMember(dest => dest.Address1, opts => opts.MapFrom(src => src.Address.Address1))
    // etc.
    .ForMember(dest => dest.Country, opts => opts.MapFrom(src => src.Address.Country));

AutoMapper.Mapper.CreateMap<CompanyViewModel, Company>()
    .ForMember(dest => dest.Address, opts => opts.MapFrom(src => new Address
        {
            Address1 = src.Address1,
            Address2 = src.Address2,
            // etc.
        }));

这似乎很多,但你只需要为你的应用程序指定一次,然后你就可以了。它可能不会帮助你现在,但将来......