这里的强制类型转换应该在哪里?LINQ to Entities 仅支持将 Entity Data Model 原始类型进行强制类型转换。

24

我有多个实体框架表,我通过它们的部分类使它们支持接口IHistoricEntityIHistoricEntity具有ActiveTo Datetime?属性。

// Auto generated LINQ to Entities domain service:
[EnableClientAccess()]
public partial class ProductService : LinqToEntitiesDomainService<ProductDBEntities>
{
    public IQueryable<ANALYSIS_CODES> GetANALYSIS_CODES()
    {
        return this.ObjectContext.ANALYSIS_CODES;
    }
 ...
}

// My Partial class to add interface
public partial class ANALYSIS_CODES : IHistoricEntity
{}

我正在尝试将这段可工作的代码重构成一个方法:

List<ANALYSIS_CODE> filtered = (from rec in ps.GetANALYSIS_CODES() where rec.ActiveTo == null select rec).ToList()

就像这样:

private List<T> Filter<T>(IQueryable<T> queryable) where T : IHistoricEntity
{
    return (from rec in queryable where rec.ActiveTo == null select rec).ToList();
}

// called like this:
List<ANALYSIS_CODE> filtered = Filter(ps.GetANALYSIS_CODES());

这在ToList上引发了异常:

无法将类型“ANALYSIS_CODES”转换为类型“IHistoricEntity”。LINQ to Entities仅支持将Entity Data Model原始类型进行转换。

但是我从未要求将其转换为IHistoricEntity。我只是说T必须支持IHistoricEntity

你试过将查询存储在变量中,在调试器中检查其表达式属性,然后再将其转换为列表吗?这应该会显示出类型转换的位置。 - wizzardmr42
那里没有任何有用的东西,而且当我尝试扩展结果时出现异常。 - weston
你尝试过显式访问.expression属性吗?在调试器中它并不总是可见,但你应该可以手动输入它。另外,在调试器中尝试query.ToString(),这可能也会给出线索(适用于Linq to SQL,我还没有尝试过Entities)。 - wizzardmr42
1个回答

46

rec.ActiveTo是你接口中定义的一个属性。因此,在访问该属性之前,Linq需要将rec强制转换为IHistoricEntity

不要被.ToList()中抛出的异常所迷惑:Linq查询只在需要记录时才被评估和执行,在本例中,当集合被转换为List<>时。

更新:我验证了@hvd的评论,并且确实添加了一个where T: class子句,它会改变Linq表达式。

System.Collections.Generic.List`1[MyType]
    .Where(x => (Convert(x).ActiveTo == Convert(null)))

为了

System.Collections.Generic.List`1[MyType]
    .Where(x => (x.ActiveTo == Convert(null)))

24
因此,Linq需要将rec转换为IHistoricEntity才能访问该属性。——几乎正确,但并非完全如此。通过在泛型参数上包含一个class约束条件,可以避免这个要求。当类型预先知道是引用类型时,转换为IHistoricEntity就是一个无操作,并且不会被包括在内。(否则,强制转换潜在地可能会是装箱操作,因为T可能是一个结构体。) - user743382
2
@hvd 很好,谢谢你们两个,where T : class, IHistoricEntity 就解决了问题。而且这也很合理! - weston
哇!我找解决方案找了好几天!而 T:class 就解决了它!非常感谢!!!1 - Alexander Vasilyev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接