Merging two iqueryables that are projected to one entity from different tables

c# entity-framework iqueryable linq merge


I have tried This answer, This one and this one to merge two iqueryables. But I always receive the following error:

The type 'Estudio' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.

I'm mapping from two different but similar Entity Framework Entities (EXAMEN and EXPLORACION) to my domain entity Estudio, with the following code.

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

var listCombined = listExamen.Concat(listExploracion);

Is there anyway of generate a IQueryable (not enumerable) with the merging of both list? If AsEnumerable() is used, then the following filters (Order, Take, etc) are executed on memory. So I need to merge the list but still be able to apply filter to the merged list wihtout execute the queries.

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

Is that possible?

5/23/2017 11:46:06 AM

Accepted Answer

I would try to select your data into an anonymous type in your linq query, perform the union, and add your criteria.

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

Note: I have no idea if you can use Common Table Expressions (the SQL necessity for skip/take) in combination with a Union-query

Note: I've changed the methods used to create the expressions, since I do not know your methods (Project, To)

So I think the solution is not to cast to a specific type, but to an anonymous type, since that probably can be translated to SQL.

Warning: didn't test it

4/2/2014 12:14:53 PM

Popular Answer

My solution was to revise my mapping code. Instead of using individual property-based mappers, I had to project the entire entity at once, making sure that all of the properties were given in the same order.

So, instead of the ForMember syntax:

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

I used the ProjectUsing syntax:

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

This must be because of the way AutoMapper constructs its projections.

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow