Automapper проекция и объединение

У меня проблема с объединением и проекциями автопромышленности.

У меня есть две сущности:

public class Entity
{
    public DateTime ActionDate { get; set; }
    public int SomeProp { get; set; }
}

public class ExtendedEntity
{
    public DateTime ActionDate { get; set; }
    public int SomeProp { get; set; }
    public int SomeOtherProp { get; set; }
}

и проекция:

public class EntityProjection
{
    public DateTime ActionDate { get; set; }
    public int SomeProp { get; set; }
    public int SomeOtherProp { get; set; }
    public string Source { get; set; }
}

я отображаю сущности в одну проекцию, у сущности нет SomeOtherProp, поэтому я установил для нее 0:

public class EntityProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<ExtendedEntity, EntityProjection>()
            .ForMember(dest => dest.Source, opt => opt.MapFrom(src => "ext entity"));

        CreateMap<Entity, EntityProjection>()
            .ForMember(dest => dest.SomeOtherProp, opt => opt.MapFrom(src => 0))
            .ForMember(dest => dest.Source, opt => opt.MapFrom(src => "entity"));
    }
}

когда я пытаюсь использовать следующий код, я получаю сообщение об ошибке:

 var entities = context.Set<Entity>()
            .Project().To<EntityProjection>();
 var extEntities = context.Set<ExtendedEntity>()
            .Project().To<EntityProjection>();
 var result = entities.Union(extEntities).OrderBy(p => p.ActionDate).ToList();

Текст ошибки: тип "UserQuery+EntityProjection" появляется в двух структурно несовместимых инициализациях в рамках одного запроса LINQ to Entities. Тип может быть...

Это означает, что свойства в проекции должны быть инициализированы в том же порядке, как я могу установить порядок инициализации свойств проекции автоматом?

1 ответ

Решение

Ответ очень поздний, и короткая версия выглядит так: "Вы не можете".

У меня был точно такой же вопрос ( Могу ли я заставить Automapper инициализировать свойства в определенном порядке?) И в итоге все сопоставил в операторе выбора LINQ.

Для простоты я сделал это статическим методом в моем DTO (сокращенный код):

        public static IQueryable<MyDto> QueryableFromTaskType1(
        IQueryable<TaskType1> query)
    {
        return query.Select(src => new MyDto()
        {
            TaskId = src.Id,
            AssetTypeName = src.Asset.AssetType.Name,
            AssetId = src.Asset.Id,
            AssetCode = src.Asset.Code,
            AssetName = src.Asset.Name,
        });
    }

        public static IQueryable<MyDto> QueryableFromTaskType2(
        IQueryable<TaskType2> query)
    {
        return query.Select(src => new MyDto()
        {
            TaskId = src.Id,
            AssetTypeName = src.AssetTypeName,
            AssetId = src.AssetId,
            AssetCode = src.AssetCode,
            AssetName = src.AssetName,
        });
    }

затем вы можете получить ваши объекты в виде IQueryable, просто пропустив их через соответствующий статический метод (который добавляет выбор в DTO - или проекты, как это иначе известно), а затем объединить или получить в результате IQueryables.

Единственным недостатком является то, что Automapper обычно работает с рекурсивным автоматическим сопоставлением, хотя я уверен, что в любом случае он не будет хорошо отображаться на SQL, так что вы, вероятно, не сильно потеряете.

Другие вопросы по тегам