使用Table Per Hierarchy继承在LINQ to Entities查询中转换为派生类型

时间:2012-08-28 19:03:58

标签: c# .net linq entity-framework linq-to-entities

我有一个具有Table Per Hierarchy继承的LINQ to实体模型。我有一个基类型的查询,我想做特定的类型相关的逻辑。例如:

IQueryable<BaseType> base = ...

// this works fine
var result = base.Select(b => b is DerivedType1 ? 1 : 2).ToList();

// this doesn't compile to SQL
var result2 = base.Select(b => b is DerivedType1 ? ((DerivedType1)b).DerivedProperty : null).ToList();

有没有办法做这样的事情而不分别处理每个派生类型的IQueryables:

// I'd rather not do this:
var resultA = base.OfType<DerivedType1>().Select(d => d.DerivedProperty);
var resultB = base.OfType<DerivedType2>().Select(d => default(int?));
var result = resultA.Concat(resultB).ToList();

5 个答案:

答案 0 :(得分:26)

LINQ-to-Entities不支持直接转换为实体类型(DerivedType1)b,但as运算符(b as DerivedType1)是,因此您可以尝试:

var result2 = base
    .Select(b => b is DerivedType1
        ? (b as DerivedType1).DerivedProperty
        : null)
    .ToList();

答案 1 :(得分:0)

您可以在您的派生类型中覆盖基础类型上的方法,以提供相关的属性值。

public class MyBaseClass
{
    public virtual int GetSomething()
    {
        throw new NotImplementedException();
    }
}

public class MyDerivedClass1 : MyBaseClass
{
    public int SomeProperty { get; set; }

    public override int GetSomething()
    {
        return this.SomeProperty;
    }
}

public class MyDerivedClass2 : MyBaseClass
{
    public int SomeOtherProperty { get; set; }

    public override int GetSomething()
    {
        return this.SomeOtherProperty;
    }
}

然后你可以:

var result = base.Select(b => b.GetSomething()).ToList();

答案 2 :(得分:0)

试试这个,我从未做过任何需要做这种事情的事情,但这应该做到。此外,如果您使用base,首先不要因为它是关键字,但如果必须,请使用@base名称前面的@表示它不用作关键字。< / p>

var resultA = base.Select(aVar =>
                            (aVar is DerivedType1) ?
                                (DerivedType)(((DerivedType1)aVar).DerivedProperty)
                                :
                                (DerivedType)(default(int?))
                        ).ToList();

答案 3 :(得分:0)

OfType<DerivedType1>() 

将返回一个IEnumerable,如果可能的话,尝试将基类型更改为IEnumerable而不是IQueryable,使用IQueryable时可能会遇到一些SQL限制。

当然,如果您实际上没有查询数据库,那么这是什么?

答案 4 :(得分:0)

您可以使用EntityFramework.Extended来提高查询的性能,而不是两次往返DB。

var resultA = base.OfType<DerivedType1>().Select(d => d.DerivedProperty).Future();
var resultB = base.OfType<DerivedType2>().Select(d => default(int?)).Future();
var result = resultA.Concat(resultB).ToList();

在这种情况下,只执行一次往返bd的往返。 这个框架对于很多其他的东西非常有用。