Существует ли универсальный способ использовать ValueResolver AutoMapper для отображения значений EntityKey для Объектов EF?

Не уверенный, если заголовок имеет смысл, но здесь - то, что я делаю. Я использую AutoMapper для отображения моих Объектов Платформы Объекта на мои объекты DTO и наоборот. Проблема прибывает, когда я пытаюсь отобразить данные DTO на объект EF. Нет свойства к свойству, отображающемуся для EntityKey. Для фиксации этого я делаю некоторым нравится следующее:

        Mapper.CreateMap<VideoDTO, Video>()
            .ForMember(dest => dest.EntityKey, opt =>   
opt.ResolveUsing<VideoEntityKeyResolver>());

Класс VideoEntityKeyResolver похож:

public class VideoEntityKeyResolver : ValueResolver<VideoDTO, EntityKey>
{
    protected override EntityKey ResolveCore(VideoDTO source)
    {
        EntityKey key = new EntityKey("EntityFrameworkTestingEntities.Videos",
            "VideoId", source.VideoId);
        return key;
    }
}

Я задавался вопросом, был ли более универсальный способ сделать это, где у меня мог быть 1 класс с конструктором, который берет Имя Множества сущностей, Ключевое Имя Свойства и Значение ключа в конструкторе.

Я думал о просто добавлении свойства EntityKey к моим объектам DTO, которое много походит на пересечение потоков, поскольку смыслом создания объектов DTO была к серьезному связь с моим слоем данных в остальной части моего приложения.

На абсолютно несвязанной ноте (я могу создать новый вопрос в случае необходимости), где точно я должен определить свои отображения при использовании AutoMapper? В настоящее время я делаю его в конструкторе моего объекта контекста (который является моим объектом репозитария EF), но я полагаю, что это является довольно дорогостоящим и просто не корректным, тем не менее, это работает.

6
задан Alex James 28 January 2010 в 01:36
поделиться

1 ответ

Я не заходил так далеко, чтобы тестировать это, но следующее должно работать:

public class EntityKeyResolver<T, TProperty> : ValueResolver<T, EntityKey> where T : class
{
    private Expression<Func<T, TProperty>> _propertyExpression;
    private string _qualifiedEntitySetName;
    private string _keyName;

    public EntityKeyResolver(string qualifiedEntitySetName, string keyName, Expression<Func<T, TProperty>> propertyExpression)
    {
        _qualifiedEntitySetName = qualifiedEntitySetName;
        _keyName = keyName;
        _propertyExpression = propertyExpression;
    }

    protected override EntityKey ResolveCore(T source)
    {
        return new EntityKey(_qualifiedEntitySetName, _keyName, ExpressionHelper.GetValue(_propertyExpression));
    }
}

ExpressionHelper является статическим класс, который я использую для оценки выражений в различных случаях. Метод GetValue выглядит следующим образом:

internal static TProperty GetValue<T, TProperty>(T obj, Expression<Func<T, TProperty>> expression) where T : class
{
    if (obj == null)
    {
        return default(TProperty);
    }

    Func<T, TProperty> func = expression.Compile();

    return func(obj);
}

Затем вы должны изменить свой код следующим образом (при условии, что VideoId - это Guid):

Mapper.CreateMap<VideoDTO, Video>()         
            .ForMember(dest => dest.EntityKey, opt => opt.ResolveUsing(new EntityKeyResolver<VideoDTO, Guid>("EntityFrameworkTestingEntities.Videos", "VideoId", v => v.VideoId)));

Возможно, более подробный, чем вы хотели. Альтернативой универсальному преобразователю могло бы быть использование MapFrom для сопоставления ключа объекта (они примерно одинаково подробны):

Mapper.CreateMap<VideoDTO, Video>()         
                .ForMember(dest => dest.EntityKey, opt => opt.MapFrom(src => new EntityKey("EntityFrameworkTestingEntities.Videos", "VideoId", src.VideoId)));

Что касается вашего другого вопроса, у меня появилась привычка создавать статический класс, который инициализирует мои карты и устанавливает логическое значение, указывающее, были ли созданы сопоставления, поскольку вам нужно вызвать его только один раз для каждого домена приложения. Затем в конструкторе своего репозитория я просто вызываю MapInitializer.EnsureMaps ();

8
ответ дан 16 December 2019 в 21:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: