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

时间:2014-04-02 11:52:01

标签: c# linq entity-framework merge iqueryable

我已尝试This answerThis onethis one合并两个iqueryable。但我总是收到以下错误:

  

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

我正在从两个不同但相似的实体框架实体(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);

这可能吗?

3 个答案:

答案 0 :(得分:3)

我会尝试在您的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。

警告:没有测试

答案 1 :(得分:3)

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

所以,而不是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
        ...
    });

这必须是因为AutoMapper构建其投影的方式。

答案 2 :(得分:0)

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

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>());