Expression.Convert使用未包含的类型

时间:2013-08-20 08:49:49

标签: c# lambda

所以这是设置

您有一个名称空间DAL和一个名称空间DTO(在不同的程序集中)。两者都包含一个类Foo。 我试图做的是在DTO类型上指定EF包含并将它们转换为DAL类型。

我们有来自前端的以下集合:

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,
                    };
    }
}

我们在另一个程序集中使用此集合,如下所示:

IQueryable<object> query = Context.Foos;

foreach (var expr in request.IncludeProperties)
{
        query = query.Include(expr);
}

var foo = query.First(x => x.Id == request.Id);

奇怪的是,此代码正在编译和执行,但包含的属性为null。 当我正在调试并将鼠标悬停在此部分上时:x => ((Foo)x).Bar调试器说Foo的类型为:DAL.Foo而不是包含的DTO.Foo。

这是因为表达式是在我们没有包含到DTO的文件中编译的,但我们有一个包含到DAL?这不是c#中的错误吗?

这是C#中预期的行为吗?

项目框架是4.0,但我正在编译4.5安装。

2 个答案:

答案 0 :(得分:1)

这不是由C#引起的。您忽略了query.Include(expr);的结果,因此Include表达式实际上并未实际应用。只要它仍未使用,它就不会引起问题:即使在常规的C#代码(没有表达式树)中,如果你有一个A类型的对象,那么将它转换为完全不同的类型{{1}使用B显然不起作用,但这会在运行时被检测到,所以只有在代码实际被调用时才会被检测到。

此外,据我所知,实体框架目前不支持多个具有相同名称的类型。它按名称查找类型,(B)(object)aDAL.Foo具有相同的名称。 EF知道的类型是它最终使用的类型。你不应该依赖这个。

答案 1 :(得分:0)

AS DAL.Foo比DTO.Foo(包含的程序集中的 )更接近(在当前程序集中),因此编译器首先选择它。这是预期和一致的行为,而不是错误。您需要明确指定名称,因此请更改此

x  => ((Foo)x).Bar, 

 x  => ((DTO.Foo)x).Bar,