自动映射投影和并集

本文关键字:投影 映射 | 更新日期: 2023-09-27 18:20:46

我对并集和自动映射器投影有问题。

我有两个实体:

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

我将实体映射到一个投影,实体没有SometherDrop,所以我将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();

错误文本:在单个LINQ to Entities查询中,类型"UserQuery+EntityProjection"出现在两个结构不兼容的初始化中。一种类型可以是…

这意味着投影中的属性必须按相同的顺序初始化,如何通过automapper设置投影属性的初始化顺序?

自动映射投影和并集

答案很晚,简短的版本似乎是"你不能"。

我也有同样的问题(我可以强制Automapper按特定顺序初始化属性吗?),最终在LINQ select语句中映射了所有内容。

为了方便起见,我在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,只需通过适当的静态方法(将select附加到DTO或其他已知的项目中)传递它们,然后对生成的IQueryables进行Union或Concat。

唯一的缺点是Automapper通常会处理递归自动映射,尽管我很确定它无论如何都不会很好地映射到SQL,所以你可能不会损失太多。

相关文章: