2013-10-03 39 views
0

我有一個與Address模型有一對一關係的公司模型。我爲創建,細節,編輯和更新操作使用了視圖模型。我正在使用AutoMapper從模型映射到視圖模型,反之亦然。AutoMapper flattening適用於查看記錄但不創建/更新?

我用來包含一個屬性暴露公司的地址視圖模型:

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正在工作(它可以拉現有公司的地址),但更新沒有進入數據庫...如果我手動將視圖模型屬性映射到公司。地址屬性它工程,但我無法弄清楚如何讓它與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); 
} 

任何幫助表示讚賞。如前所述,我總是可以從視圖模型手動映射到對象來更新/創建(事實上,有些人會認爲這是寫入數據庫的一種更好的做法),但我很好奇爲什麼映射在一個方向上工作只有...請讓我知道,如果你需要更多的代碼...

回答

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. 
     })); 

這看起來很多,但你只需要指定一次,對你的應用程序,並那麼你很好去。它可能不會幫你現在,但在未來...

+0

我不介意像這樣定製地圖(實際上可能更喜歡知道它的佈局正確,而不是「神奇地」由AutoMapper決定),但我很好奇,爲什麼我的更新不起作用! – Jim

+0

因此,對我之前的問題發表評論,證實這是正確的解決方案 - 顯然,展平不會自動反向工作。我繼續前進,並定義了我的地圖,如下所示,這使我可以1)獲得更高級別的舒適度,這些東西將被正確映射,並且2)擺脫ViewModel中時髦的屬性名稱(AddressAddress1)。謝謝,+1! – Jim

相關問題