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

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

IQueryable 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().Select(d => d.DerivedProperty); var resultB = base.OfType().Select(d => default(int?)); var result = resultA.Concat(resultB).ToList(); 

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

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

您可以在基类型上使用一种方法,该方法在派生类型中被覆盖,以提供相关的属性值。

 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(); 

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

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

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

那当然,如果你实际上没有查询数据库?

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

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

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