2012-03-09 14 views
1

私はautomapperを使用して、1つのDBからわずかに異なる構造の新しいDBにインポートしています。私は以下のTargetTypeのようなコード表をどのように扱うかはわかりません。 Automapperは、インポート時に重複を作成しているようです(「Models.ShipTarget_TargetTypeの関係の主な終点を特定できません。複数のエンティティが同じ主キーを持つことがあります」、db.SaveChanges())。私は多対多の関係でも同じ問題を抱えていましたが、ブリッジテーブルでAutoMapperが任意の制約に違反することなく複写物を幸せに作成できるので、そこにエラーはありません。重複を生成せずにコードテーブルでAutoMapperを使用するにはどうすればよいですか?

つまり、ShipTargetをマッピングすると(多くのものがあります)、TargetTypeフィールドをマッピングすると(少数のTargetTypesしかありません)、ターゲットに既に存在するかどうかをチェックするのではなく、常に新しいTargetTypeを作成します既存のインスタンスを使用します。 TargetTypeはコードテーブルなので、多くのShipTargetで共有されている特定の値に対して同じインスタンスが必要です。

変更の保存が呼び出される前に、すべてのマッピングが1回のパスで実行されていることに注意してください。だから、絶対にTargetTypesのどれもがデスティネーションデータベースに存在しないので、ソースコードテーブルからそれぞれを作成することを期待しますが、各ShipTargetが一意のTargetTypeを参照しているかのように重複を作成しています。私は、ソースDBにShipTargetTypesがあるので、それが唯一のように多くのTargetTypesを作成していることを確認するにはどうすればよい

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

私の現在のマッピングは、この(簡体字、うまくいけば何のタイプミス)ではありませんか?複数の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

私は以下をやってみたかった:

この擬似コードは、私が問題を解決しなければならなかったが、これはかなり複雑なようだと、私はそれが正しいとにかく働いて得るために正確にどのようにわからないんだけど1つのアイデアを表現しますTargetTypeのConvertUsingで、コードテーブルが参照されていたどこにでも適用できるようになりましたが、デフォルトのマッピングを使用して新しいテーブルを作成する方法を理解できませんでした私が行っているところは以下ですMapper.Map(srcTarget.ShipTarget, newTarget.TargetType);

コードテーブルを参照するクラスのメンバではなく、最初に無視するように指示します新しいコードテーブルにそのエントリが存在するかどうかをチェックし、そのエントリを使用して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); 
     } 
     } 
    }); 
関連する問題