2012-11-29 204 views
1

型號我有一個支架型號:映射DTO回用AutoMapper

public partial class Fixture 
{ 
    public int FixtureId { get; set; } 
    public string Season { get; set; } 
    public byte Week { get; set; } 

    //foreign key 
    public int AwayTeamId { get; set; } 
    //navigation properties 
    public virtual Team AwayTeam { get; set; } 

    //foreign key 
    public int HomeTeamId { get; set; } 
    //navigation properties 
    public virtual Team HomeTeam { get; set; } 

    public byte? AwayTeamScore { get; set; } 
    public byte? HomeTeamScore { get; set; } 
} 

以及器具DTO:

public class FixtureDTO 
{ 
    public int Id { get; set; } 
    public string Season { get; set; } 
    public byte Week { get; set; } 
    public string AwayTeamName { get; set; } 
    public string HomeTeamName { get; set; } 
    public byte? AwayTeamScore { get; set; } 
    public byte? HomeTeamScore { get; set; } 
} 

我使用AutoMapper的映射,這是使用它我第一次嘗試。這裏是我的映射:

CreateMap<Fixture, FixtureDTO>() 
      .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.FixtureId)) 
      .ForMember(dest => dest.AwayTeamName, opt => opt.MapFrom(src => src.AwayTeam.TeamName)) 
      .ForMember(dest => dest.HomeTeamName, opt => opt.MapFrom(src => src.HomeTeam.TeamName)); 
     CreateMap<FixtureDTO, Fixture>(); 

它可以在拍攝夾具並將其映射到FixtureDTO,我用它來顯示數據正常。但是,當我想更新數據並通過FixtureDTO回映射回夾具我得到一個錯誤。

public HttpResponseMessage PutFixture(int id, FixtureDTO fixture) 
    { 
     if (ModelState.IsValid && id == fixture.Id) 
     { 
      //do mapping manually here? 

      var updated = _repository.UpdateFixture(Mapper.Map<Fixture>(fixture)); 
      return Request.CreateResponse(updated ? HttpStatusCode.OK : HttpStatusCode.NotFound); 
     } 
     return Request.CreateResponse(HttpStatusCode.BadRequest); 
    } 

這是錯誤我得到:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries. 

任何人可以在這方面幫助?

編輯:當實體您嘗試這通常發生:反向映射:

CreateMap<Fixture, FixtureDTO>() 
      .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.FixtureId)) 
      .ForMember(dest => dest.AwayTeamName, opt => opt.MapFrom(src => src.AwayTeam.TeamName)) 
      .ForMember(dest => dest.HomeTeamName, opt => opt.MapFrom(src => src.HomeTeam.TeamName)); 
     CreateMap<FixtureDTO, Fixture>() 
      .ForMember(dest => dest.FixtureId, opt => opt.MapFrom(src => src.Id)) 
      .ForMember(dest => dest.AwayTeam.TeamName, opt => opt.MapFrom(src => src.AwayTeamName)) 
      .ForMember(dest => dest.HomeTeam.TeamName, opt => opt.MapFrom(src => src.HomeTeamName)); 

回答

0

@ lazyberezovsky的擴展回答:

這是您可能需要的反向映射(未經測試)的示例:

CreateMap<FixtureDTO, Fixture>() 
     .ForMember(dest => dest.FixtureId, 
        opt => opt.MapFrom(src => src.Id)) 
     .ForMember(dest => dest.AwayTeam, 
        opt => opt.MapFrom(src => new Team 
               { 
                TeamName = src.AwayTeamName 
               })) 
     .ForMember(dest => dest.HomeTeam, 
        opt => opt.MapFrom(src => new Team 
               { 
                TeamName = src.HomeTeamName 
               })); 

我已經使用在過去和它工作得很好這種格式,但或者你也可以創建團隊特定的映射。例如:

CreateMap<string, Team>().... 

此外,我認爲你這樣做,但斷言你的配置是有效的。例如:

[Test] 
public void AutoMapper_Configuration_IsValid() 
{ 
    Mapper.Initialize(m => m.AddProfile<MyProfile>()); 
    Mapper.AssertConfigurationIsValid(); 
} 
+0

我認爲這是正確的軌道,但我有一個事實,即我有超過1個團隊對象的問題,並且映射不會映射TeamId,所以我最終得到2個0的teamId,這導致此錯誤:'具有相同密鑰的對象已經存在於ObjectStateManager中。 ObjectStateManager不能使用同一個鍵'追蹤多個對象'。我是否需要進入數據庫並映射TeamIds? – user517406

+0

問題中沒有足夠的信息來定義'Team'應該如何映射,所以我簡單地調整了你的映射。您有幾個選項,可以在原始請求中獲取'Team.ID',並通過視圖中的隱藏字段保存它,或者使用團隊名稱查詢數據庫以在回發期間再次檢索ID。 – Mightymuke

0

普遍認爲異常是由EF拋出,當它檢測到以下之一:

Opimistic併發衝突編輯被修改,否則在你加載,編輯和保存的時候。 (請參閱:Entity Framework: "Store update, insert, or delete statement affected an unexpected number of rows (0)."

錯誤設置ID:沒有爲Pks或FK設置ID。我也看到類似這樣的,當我錯誤地設置一個實體的FK的值和相關的對象用不同的ID設置到對象的異常。

這很可能異常被拋出的,因爲在你的倉庫一些代碼。如果您將代碼發佈到存儲庫中,我們可能會更好地瞭解導致異常的原因。

+0

這是在我的倉庫的相關代碼:公共BOOL UpdateFixture(治具夾具) { _db.Entry(夾具).STATE = EntityState.Modified; 嘗試 { _db.SaveChanges(); 返回true; } catch(DbUpdateConcurrencyException) { return false; } } – user517406

+0

在這種情況下,我會假設它可能是您的映射問題。 @lazyberezovsky是正確的,默認情況下你不能映射到子屬性(例如'dest.AwayTeam.TeamName'),你需要編寫你自己的自定義解析器(https://github.com/AutoMapper/AutoMapper/wiki/定製值解析器)。 – jstromwick

0

首先,你需要從DTO創建反向映射到實體(提供自定義成員映射,如果需要的話):

Mapper.CreateMap<FixtureDTO, Fixture>(); 

其次 - 檢索,地圖,和更新現有的實體

if (ModelState.IsValid && id == fixture.Id) 
{ 
    Fixture entity = _repository.FindById(fixture.Id); 
    Mapper.Map(fixture, entity); // Use this mapping method! 
    var updated = _repository.UpdateFixture(entity); 
    // etc 
} 
+0

Mapper.Map行給我以下錯誤:「缺少類型映射配置或不支持的映射。\ n \ n映射類型:\ r \ nFixtureDTO - > Fixture_E5E73096DAC63B49875D0DFBD914D9991F1B1DE2AF3D92F26A5A11D99374E380 \」}。爲什麼它會試圖將FixtureDTO映射到Fixture_E5E73096DAC63B49875D0DFBD914D9991F1B1DE2AF3D92F26A5A11D99374E380? – user517406

+0

@ user517406這就是我在第一部分討論過的 - 你需要爲這個映射創建映射。並且automapper試圖將FixtureDTO映射到Fixture,因爲你需要更新你的Fixture。 –

+0

執行從FixtureDTO到Fixture的反向映射(請參閱原始帖子中的編輯)會導致錯誤:表達式'dest => dest.AwayTeam.TeamName'必須解析爲頂級成員,而不是任何子對象的屬性。改爲在子類型或AfterMap選項上使用自定義解析器。 – user517406