合并从不同表中投影到一个实体的两个 iqueryable

本文关键字:实体 一个 iqueryable 两个 投影 合并 | 更新日期: 2023-09-27 17:56:23

我已经尝试过这个答案,这个和这个来合并两个可查询对象。但我总是收到以下错误:

类型"Estudio"出现在单个 LINQ to 实体查询中的两个结构不兼容的初始化中。可以在同一查询中的两个位置初始化类型,但前提是在两个位置设置了相同的属性,并且这些属性的设置顺序相同。

我使用以下代码从两个不同但相似的实体框架实体(EXAMEN 和 EXPLORACION)映射到我的域实体 Estudio。

IQueryable<Estudio> listExamen = context.Set<EXAMEN>().Project().To<Estudio>();
IQueryable<Estudio> listExploracion = context.Set<EXPLORACION>().Project().To<Estudio>();
var listCombined = listExamen.Concat(listExploracion);

无论如何,通过合并两个列表来生成一个 IQueryable(不可枚举)吗?如果使用 AsEnumerable(),则会在内存上执行以下筛选器(Order、Take 等)。所以我需要合并列表,但仍然可以在不执行查询的情况下将过滤器应用于合并的列表。

//This will force the next condition is executed on memory
    var listCombined = listExamen.AsEnumerable().Concat(listExploracion);

这可能吗?

合并从不同表中投影到一个实体的两个 iqueryable

我会尝试在 linq 查询中选择匿名类型中的数据,执行联合并添加条件。

var listExamen = context.Examen
    .Select(x => new { x.Prop1, x.Prop2, ... }); // Add properties
var listExploracion = context.Exploraction
    .Select(x => new { x.Prop1, x.Prop2, ... }); // Add identical properties
var listCombined = listExamen.Concat(listExploracion);
var whereAdded = listCombines
    .Where(x => x.Prop1 == someValue);
var result = whereAdded
    .Skip(skipCount)
    .Take(takeCount)
    .ToList();

注意:我不知道您是否可以将公用表表达式(跳过/获取的SQL必要性)与联合查询结合使用

注意:我已经更改了用于创建表达式的方法,因为我不知道您的方法(ProjectTo

所以我认为解决方案不是强制转换为特定类型,而是转换为匿名类型,因为它可能可以转换为 SQL。

警告:未进行测试

我的解决方案是修改我的映射代码。我必须一次投影整个实体,而不是使用单个基于属性的映射器,确保所有属性都以相同的顺序给出。

因此,而不是ForMember语法:

Mapper.CreateMap<Client, PersonResult>()
    .ForMember(p => p.Name, cfg => cfg.MapFrom(c => c.Person.FirstName + " " + c.Person.LastName))
    ...

我使用了ProjectUsing语法:

Mapper.CreateMap<Client, PersonResult>()
    .ProjectUsing(c => new PersonResult()
    {
        Name = c.Person.FirstName + " " + c.Person.LastName
        ...
    });

这一定是因为自动映射器构建其投影的方式。

解决此问题的一种方法是添加虚拟类型:

class Estudio<T> : Estudio { }

和新的映射:

Mapper.CreateMap<Estudio , Estudio>();
Mapper.CreateMap<EXAMEN , Estudio<EXAMEN>>();
Mapper.CreateMap<EXPLORACION, Estudio<EXPLORACION>>();

需要注意的是,Estudio中的所有字段都需要一些映射值。不能使用忽略。返回0""是可以的。现在我们可以做:

var a = context.Set<EXAMEN>().ProjectTo<Estudio<EXAMEN>>();
var b = context.Set<EXPLORACION>().ProjectTo<Estudio<EXPLORACION>>();
return a.ProjectTo<Estudio>().Concat(b.ProjectTo<Estudio>());