2010-09-14 2 views
2

Я хотел бы использовать Automapper для сопоставления объектов моей модели с объектами базы данных. Пусть говорят, что объект базы данных - более 30 полей, и я хочу отобразить 10 из 20 свойств из моей модели. Чтобы сделать его более сложным, мне нужно сопоставить различные свойства при обновлении записи, чем когда я вставляю новую запись в базу данных.Использование Automapper для сопоставления больших моделей домена для объектов базы данных

Решение, которое я использую, состоит в том, чтобы создать 2 общих класса. Вставить и обновить и отобразить профиль, который задает оба сопоставления.

В приведенном ниже примере:

public abstract class SyncMappingWrapper<TFrom> where TFrom : class 
{ 
    protected SyncMappingWrapper(TFrom model) 
    { 
     Model = model; 
    } 

    public TFrom Model { get; private set; } 
} 

public class Update<TFrom> : SyncMappingWrapper<TFrom> where TFrom : class 
{ 
    public Update(TFrom model) 
     : base(model) 
    { 
    } 
} 

public class Insert<TFrom> : SyncMappingWrapper<TFrom> where TFrom : class 
{ 
    public Insert(TFrom model) 
     : base(model) 
    { 
    } 
} 

Отображение, однако, становится противным сложности цикломатической идет в небо (более 50), как мне нужно определить Игнорировать() для всех свойств я не карта:

CreateMap<Update<OracleModel>, LiveModel>() 
      .ForMember(des => des.ApprovedBy, opt => opt.Ignore()) 
      .ForMember(des => des.ApprovedDate, opt => opt.Ignore()) 
      ... 
      .ForMember(des => des.UNSPSC, opt => opt.Ignore()) 
      .ForMember(des => des.BaseUnit, opt => opt.MapFrom(src => src.Model.UOM.BaseUOM.PerSalesUnit)) 
      .ForMember(des => des.BaseUOM, opt => opt.MapFrom(src => src.Model.UOM.BaseUOM.UnitOfMeasure.Code)) 
      .ForMember(des => des.SalesUnit, opt => opt.MapFrom(src => src.Model.UOM.SalesUOM.PerSalesUnit)) 
      .ForMember(des => des.SalesUOM, opt => opt.MapFrom(src => src.Model.UOM.SalesUOM.UnitOfMeasure.Code)) 
      .ForMember(des => des.OrderUnit, opt => opt.MapFrom(src => src.Model.UOM.OrderUOM.PerSalesUnit)) 
      .ForMember(des => des.OrderUOM, opt => opt.MapFrom(src => src.Model.UOM.OrderUOM.UnitOfMeasure.Code)) 
      .ForMember(des => des.SalesPrice, opt => opt.MapFrom(src => src.Model.Price.Value)) 
      .ForMember(des => des.Alternate, opt => opt.Ignore()) 
      .ForMember(des => des.ManufacturerID, opt => opt.Ignore()) 
      .ForMember(des => des.ProductCode, opt => opt.MapFrom(src => src.Model.ProductCode)) 
      .ForMember(des => des.ProductName, opt => opt.MapFrom(src => src.Model.ProductName)) 
      .ForMember(des => des.ProductHTML, opt => opt.Ignore()) 
      .ForMember(des => des.Version, opt => opt.Ignore()) 
      ... 
      .ForMember(des => des.UnitsOfMeasure2, opt => opt.Ignore()) 
      .ForMember(des => des.Manufacturer, opt => opt.Ignore()); 

Я решил эту проблему для вставки новой записи путем создания нового объекта:

CreateMap<Insert<OracleModel>, LiveModel>() 
      .ConstructUsing(x => new LiveModel 
       { 
        BaseUnit = x.Model.UOM.BaseUOM.PerSalesUnit, 
        BaseUOM = x.Model.UOM.BaseUOM.UnitOfMeasure.Code, 
        SalesUnit = x.Model.UOM.SalesUOM.PerSalesUnit, 
        SalesUOM = x.Model.UOM.SalesUOM.UnitOfMeasure.Code, 
        OrderUnit = x.Model.UOM.OrderUOM.PerSalesUnit, 
        OrderUOM = x.Model.UOM.OrderUOM.UnitOfMeasure.Code, 
        SalesPrice = x.Model.Price.Value, 
        LeadTime = x.Model.LeadTime, 
        ProductCode = x.Model.ProductCode, 
        ProductName = x.Model.ProductName, 
        SupplierCode = x.Model.SupplierCode, 
        Weight = x.Model.Weight 
       }) 
      .ForAllMembers(xc => xc.Ignore()); 

Но это не работает для обновлений, где я хочу отобразить свойства существующего объекта и не новый экземпляр:

 Mapper.Map(update, existingRecord); 

Я бы предпочел, чтобы избежать DynamicMap(), чтобы сохранить полный контроль над отображением (так что я буду не сопоставить случайное свойство по ошибке). Моя цель - решить проблему циклической сложности. Пожалуйста, не предлагайте ValueInjecter или любые другие методы. Я ищу решение в AutoMapper.

+0

вы когда-нибудь найти способ обойти это ? Я в том же квесте:/ –

+0

Нет, я упростил свою модель. Тем не менее, я считаю, что ответ Thiago Sá должен работать для текущей версии AutoMapper. –

ответ

1

Это пять лет спустя, но вот предложение уменьшить эту проблему сложности сопоставления. Вы можете создать расширение, которое поможет вам игнорировать все члены в первой:

public static class AutoMapperExtension { 
    public static IMappingExpression<TSource, TDest> IgnoreAllMembers<TSource, TDest>(this IMappingExpression<TSource, TDest> expression) { 
     expression.ForAllMembers(opt => opt.Ignore()); 
     return expression; 
    } 
} 

Затем вы используете его, чтобы определить только отображения, которые вы хотите выполнить:

Mapper.CreateMap<Insert<OracleModel>, LiveModel>() 
     .IgnoreAllMembers() 
     .ForMember(d => d.BaseUnit, o => o.MapFrom(s => s.Model.UOM.BaseUOM.PerSalesUnit)) 
     /* Mapping for other members here. */; 
Смежные вопросы