2015-10-17 62 views
0

全部。例如,我們有這樣一個簡單的類未映射嵌套集合內的Automapper無法正常工作

public class SimpleModel 
{ 
    public int PropertyId { get; set; } 

    public ICollection<SimpleModelCollectionItem> SimpleCollection { get; set; } 
} 

public class SimpleModelCollectionItem 
{ 
    public int PropertyId { get; set; } 
} 

public class SimpleEntity 
{ 
    public int Id { get; set; } 
    public int PropertyId { get; set; } 

    public virtual ICollection<SimpleEntityCollectionItem> SimpleCollection { get; set; } 
} 

public class SimpleEntityCollectionItem 
{ 
    public int Id { get; set; } 
    public int PropertyId { get; set; } 
} 

,我們有一些配置代碼

AutoMapper.Mapper.CreateMap<SimpleModel, SimpleEntity>() 
      .ForMember(dest => dest.Id, src => src.Ignore()) 
      .ForMember(dest => dest.SimpleCollection, src => src.UseDestinationValue()); 

     AutoMapper.Mapper.CreateMap<SimpleModelCollectionItem, SimpleEntityCollectionItem>() 
      .ForMember(dest => dest.Id, src => src.Ignore()); 

     AutoMapper.Mapper.AssertConfigurationIsValid(); 

和測試數據初始化

  var model = new SimpleModel 
         { 
          PropertyId = 2, 
          SimpleCollection = 
           new List<SimpleModelCollectionItem> 
            { 
             new SimpleModelCollectionItem 
              { 
               PropertyId = 7 
              } 
            } 
         }; 
     var entity = new SimpleEntity 
         { 
          Id = 1, 
          PropertyId = 3, 
          SimpleCollection = 
           new List<SimpleEntityCollectionItem> 
            { 
             new SimpleEntityCollectionItem 
              { 
               Id = 5, 
               PropertyId = 4 
              } 
            } 
         }; 
     AutoMapper.Mapper.Map(model, entity); 

,我希望看到

Console.WriteLine(entity.Id); // 1 
Console.WriteLine(entity.PropertyId); // 2 
Console.WriteLine(entity.SimpleCollection.First().Id); // 5 but was 0 
Console.WriteLine(entity.SimpleCollection.First().PropertyId); // 7 

是否有可能內部收集的Id等於5,因爲它最初是?

回答

1

因此,當AutoMapper映射您的集合時,它實際上會從目標集合中刪除舊項目,然後添加一個新項目。

您可以通過使用此代碼驗證這一點:

var item_before = entity.SimpleCollection.First(); 

AutoMapper.Mapper.Map(model, entity); 

var item_after = entity.SimpleCollection.First(); 

bool item_same_references = object.ReferenceEquals(item_before, item_after); 

item_same_references值將是false

即使您使用的是src => src.UseDestinationValue(),也會發生這種情況。使用這隻意味着它自己的集合對象應該被重用,但不是該集合中的項目。

我不確定是否有辦法告訴AutoMapper也使用相同的收集項目。

另外,考慮一下,如果目標集合包含的源項目集合數量少於目標集合,會發生什麼情況?

因此,您得到的零是因爲當AutoMapper創建要添加到集合中的新項目時,Id屬性的默認值爲default(int),該值爲零。

我建議如下:

我假設在源和目的地集合項目的數量是相等的。

首先,修改映射配置指示AutoMapper忽略這樣的集合:

AutoMapper.Mapper.CreateMap<SimpleModel, SimpleEntity>() 
    .ForMember(dest => dest.Id, opt => opt.Ignore()) 
    .ForMember(dest => dest.SimpleCollection, opt => opt.Ignore()); 

然後,創建一個方法,這樣,在地方收集的物品映射(不刪除,然後添加新項目)像這樣的:

public void MapCollectionsInPlace<TSource, TDestination>(IEnumerable<TSource> source_collection, 
    IEnumerable<TDestination> destination_collection) 
{ 
    var source_enumerator = source_collection.GetEnumerator(); 
    var destination_enumerator = destination_collection.GetEnumerator(); 

    while (source_enumerator.MoveNext()) 
    { 
     if(!destination_enumerator.MoveNext()) 
      throw new Exception("Source collection has more items than destination collection"); 

     AutoMapper.Mapper.Map(source_enumerator.Current, destination_enumerator.Current); 
    } 
} 

現在,你可以使用下面的代碼:

AutoMapper.Mapper.Map(model, entity); 

MapCollectionsInPlace(model.SimpleCollection, entity.SimpleCollection);