2012-03-09 67 views
1

我使用automapper從一個數據庫導入到一個結構稍有不同的新數據庫中。我不知道如何處理下面的代碼表,如TargetType。 Automapper似乎在導入它們時會創建重複項(「無法確定'Models.ShipTarget_TargetType'關係的主體端,多個添加的實體可能具有相同的主鍵。」on db.SaveChanges())。我也遇到了與多對多關係相同的問題,但是我沒有在那裏發現錯誤,因爲橋表允許AutoMapper在不違反任何限制的情況下快速創建重複項。如何在代碼表上使用AutoMapper而不產生重複?

換句話說,當映射ShipTarget(有很多這些)時,當它映射TargetType字段(只有少數TargetTypes)時,它總是創建一個新的TargetType,而不是檢查它是否已經存在於目標中並使用預先存在的實例。由於TargetType是一個代碼表,因此我希望同一個實例可以在許多ShipTargets中共享一個特定的值。

請注意,在保存更改被調用之前,所有映射都在一次完成。所以目標數據庫中絕對沒有TargetTypes,所以我期望它會從源代碼表中創建一個TargetType,但它會創建重複項,就像每個ShipTarget引用一個唯一的TargetType一樣。

我當前的映射是這樣的(簡化,幸而沒有錯別字):

var src2NewShip = Mapper.CreateMap<SourceDataModel.Ship, Ship>() 
     .ForMember(newShp => newShp.Targets, c => c.MapFrom(srcShp => srcShp.ShipTargets)); 

var srcShipTargetType2NewTargetType = Mapper.CreateMap<SourceDataModel.ShipTargetType, TargetType>(); 

var srcShipTarget2SrcTarget = Mapper.CreateMap<SourceDataModel.ShipTarget, ShipTarget>() 
      .ForMember(newTarget => newTarget.TargetType, c => c.MapFrom(srcTarget => srcTarget.ShipTargetType)); 

我如何確保它只是作爲有源數據庫ShipTargetTypes,創建多TargetTypes?而不是在被多個ShipTarget引用時複製它們。

這個僞代碼表示我有一個想法來解決問題,但是這似乎很令人費解,我不知道究竟是如何得到它的權利,無論如何努力:

var srcShipTarget2SrcTarget = Mapper.CreateMap<SourceDataModel.ShipTarget, ShipTarget>() 
      .ForMember(newTarget => newTarget.TargetType, c => c.MapFrom(srcTarget => 
{ 
    newDb.Ships.SelectMany(s => s.ShipTargets).FirstOrDefault(st=>st.TargetType.UniqueName == srcTarget.UniqueName); 
//here I would return the found instance, or call upon automapper to map srcTarget to a new TargetType and return that 
//essentially, use existing, or return new 
); 


public class TargetType 
    { 
    [Key] 
    public int TargetTypeKey { get; set; } 

    public string UniqueName { get; set; } 
    ... 
    } 

    public class ShipTarget 
    { 
    [Key] 
    public int ShipTargetKey { get; set; } 

    public int ShipKey { get; set; } 
    [ForeignKey("ShipKey")] 
    public Ship Ship { get; set; } 

    public int TargetTypeKey { get; set; } 
    [ForeignKey("TargetTypeKey")] 
    public TargetType TargetType { get; set; } 

    ... 
    } 

    public class Ship 
    { 
    [Key] 
    public int ShipKey { get; set; } 

    public virtual ICollection<ShipTarget> Targets { get; set; } 
    ... 
    } 

回答

0

我想做的下方在Tar​​getType的ConvertUsing中,這樣它就可以應用到引用代碼表的任何地方,但我無法弄清楚如何告訴它使用默認映射來創建一個新映射(如果它不存在的話),比如在我在下面做Mapper.Map(srcTarget.ShipTarget, newTarget.TargetType);

因此,對於引用代碼表的類的成員,我告訴它最初igno然後將它映射到AfterMap中,方法是檢查條目是否存在於新代碼表中,使用該條目,如果該條目不存在,則創建一個新條目。

var srcShipTarget2SrcTarget = Mapper.CreateMap<SourceDataModel.ShipTarget, ShipTarget>() 
    .ForMember(newTarget => newTarget.TargetType, c => c.Ignore()) 
    .AfterMap((srcTarget, newTarget) => 
    { 
     if (srcTarget.ProjectTargetType != null) 
     { 
     newTarget.TargetType = db.TargetTypes.FirstOrDefault(tt => tt.UniqueName == odsT.ProjectTargetType.UniqueName); 
     if (newTarget.TargetType == null) 
     { 
      newTarget.TargetType = Mapper.Map(srcTarget.ShipTarget, newTarget.TargetType); 
     } 
     } 
    }); 
相關問題