Reputation: 6151
So this is the Setup
You have a namespace DAL and a namespace DTO (In a different assembly). Both contain a class Foo. What I was trying to do, is to specify EF includes on a DTO type and convert them to a DAL type.
We have the following collection coming from the front-end:
using DTO;
public class GetFooById : Request
{
public GetFooById()
{
IncludeProperties = new HashSet<Expression<Func<object, object>>>
{
x => ((Foo)x).Bar, //DTO.Foo, when debugging is DAL.Foo
x => ((Foo)x).Foobars,
};
}
}
We use this collection in another assembly, something like this:
IQueryable<object> query = Context.Foos;
foreach (var expr in request.IncludeProperties)
{
query = query.Include(expr);
}
var foo = query.First(x => x.Id == request.Id);
The strange part is, this code is compiling and executing, but the included properties are null.
When I'm debugging and hover over this part: x => ((Foo)x).Bar
The debugger says Foo
is of type: DAL.Foo instead of the included DTO.Foo.
Is this because the expression is compiled in a file where we don't have an include to DTO, but we have an include to DAL? Isn't this a bug in c# ?
Is this expected behavior in C# ?
Project framework is 4.0, but i'm compiling with 4.5 installed.
Upvotes: 0
Views: 96
Reputation:
This is not caused by C#. You're ignoring the result of query.Include(expr);
, so the Include
expression does not actually get applied anyway. As long as it remains unused, it cannot cause problems: even in regular C# code (without expression trees), if you've got an object of type A
, then casting it to a completely distinct type B
using (B)(object)a
would obviously not work, but this would be detected at runtime, so only if the code actually gets called.
Also, Entity Framework does not currently support multiple types with the same name, as far as I am aware. It looks up types by name, and DAL.Foo
and DTO.Foo
have the same name. The type that EF knows about is the type that it ends up using. You should not rely on this.
Upvotes: 1
Reputation: 32729
AS DAL.Foo is closer(in current assembly) than DTO.Foo (in an included assembly) hence the compiler picks it up first. It is expected and consistent behaviour, not a bug. You need to specify the name explicitly so, change this
x => ((Foo)x).Bar,
to
x => ((DTO.Foo)x).Bar,
Upvotes: 0