gan
gan

Reputation: 43

Need to cast explicitly thru anonymous type in Union()

I have 2 var/objects, retrieving thru these 2 functions:

private IQueryable<Project> SelectAll_1(...)
{
    return query;
}

class Project is:

private int ID;
private string col1;
private string col2;
private string col3;

and another:

private IQueryable<Project_test> SelectAll_2(...)
{
    return query;
}

where POCO of is:

private string ID_inString;
private string col1;
private string col2;
private string col3;

and i need to perform union on both of them,

var P2 = SelectAll_2(...);
var P1 = SelectAll_1(...);

var P3 = P2.Union(P1);

but i get an error, mentioning:

The type arguments for method 'System.Linq.Queryable.Union(System.Linq.IQueryable, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

i saw some people solve it thru' anonymous type, but i not sure how it works. Anyone has any idea?

Upvotes: 4

Views: 2932

Answers (2)

Anders Abel
Anders Abel

Reputation: 69260

The problem is that P2 is an IQueryable<Project> while P3 is an IQueryable<Project_test> and you can't union them into one sequence, since they are of different type.

What you need to do is to project both of them into one common type with a Select() call which as far as I know must be a named type according to Jon Skeet can be done with an anonymous type. The initialization blocks that define the anonymous types must have the same number of members, with the same name, in the same order, with the same types to be treated as one type. To project the types with Select() you also need to make the properties public to be accessible for the linq methods.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500185

You can't union two different types, unless one inherits from the other (for example, you could potentially find a union of IEnumerable<object> and IEnumerable<string>, although that would rarely be useful).

Now in your case, it sounds like Project and Project_test should really be one type, if the various properties have the same meaning. Currently the ID properties have different types - but is that really necessary or desirable? If they're both identifiers with the same scope, it makes sense to store them in the same representation. If the properties don't have the same meaning, you shouldn't be forming a union between them at all. If they do have the same meaning, you should try to make both sequences use the same type.

You could use anonymous types for this, in this way:

var projectedP1 = P1.Select(x => new { x.ID, x.col1, x.col2, x.col3 });
var projectedP2 = P2.Select(x => new { ID = int.Parse(x.ID_inString),
                                            x.col1, x.col2, x.col3 });
var union = projectedP1.Union(projectedP2);

Or you could just use one of the existing types:

var projectedP1 = P1.Select(x => new Project_test { 
                                     ID_inString = x.ID.ToString(), 
                                     col1 = x.col1, 
                                     col2 = x.col2, 
                                     col3 = x.col3 });
var union = projectedP1.Union(P2);

It's not really obvious which of these is a better idea - but I'd go back to trying to reconcile the two types if possible, at which point you have no problems anyway.

Upvotes: 5

Related Questions