24

我有一个具有按层次结构表继承的 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();
4

5 回答 5

31

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

var result2 = base
    .Select(b => b is DerivedType1
        ? (b as DerivedType1).DerivedProperty
        : null)
    .ToList();
于 2013-04-18T16:49:47.947 回答
1
OfType<DerivedType1>() 

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

那当然是如果您实际上不是在查询数据库?

于 2013-04-18T13:49:24.220 回答
1

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

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 的往返行程。这个框架对 int EF 的许多其他事情非常有用

于 2013-07-23T19:15:42.467 回答
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();
于 2012-08-31T11:55:32.983 回答
0

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

var resultA = base.Select(aVar =>
                            (aVar is DerivedType1) ?
                                (DerivedType)(((DerivedType1)aVar).DerivedProperty)
                                :
                                (DerivedType)(default(int?))
                        ).ToList();
于 2013-01-09T01:16:07.857 回答