如果我在 Entity Framework 中有三个类。
class Base {}
class Left : Base {}
class Right : Base {}
然后我调用 DBContext.Bases.ToList();
这将返回 Base
的所有实例,并将其完全类型化为其关联的继承类型,正如某些人已经注意到的那样,EF 在大型继承结构上的性能至少可以说不是很好。我在项目中的实际查询有 600 行长,仅用于返回一个实体并需要 2 秒才能生成。
如果您告诉它返回哪种类型,它们的查询运行速度会快得多,因为它不必连接整个结构。例如
DBContext.Bases.OfType<Left>.ToList();
or
DBContext.Bases.OfType<Right>.ToList();
但是我现在想只返回基类。不幸的事
DBContext.Bases.OfType<Base>.ToList();
作用与 DBContext.Bases.ToList();
它获得了整个继承结构...有什么方法(无需在 EF 中创建新类型)在查看 Base 集合时仅返回类 Base?
抱歉,我无法登录我的实际帐户...
也许我没说清楚,我想带回所有对象(包括Base、Left 和Right)但我只想返回Base 类,即使在数据库中它们是实际的Left 和Right 类。
OFTYPE 是一个很好的建议,但它过滤掉了我所有的实体,因为没有一个是实际的基本类型。但我只想返回 Base 类型对象中的 Base 类型值。
有什么想法吗?
最佳答案
GetType()
Entity Framework 不理解,但关键字 is
确实有效。因此,您可以构建一个表达式并将其应用于您的查询。此处的代码应该适用于 EF5+ 添加一个扩展方法,您可以将其调用为:query.OfOnlyType<Base, SubTypeWithDescendants>()
. (或者如果需要,可以使用相同的两个 Type 参数,尽管我的层次结构比这更复杂)
public static IQueryable<ReturnType> OfOnlyType<ReturnType, QueryType>
(this IQueryable<QueryType> query)
where ReturnType : QueryType {
// Look just for immediate subclasses as that will be enough to remove
// any generations below
var subTypes = typeof(ReturnType).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(ReturnType)));
if (subTypes.Count() == 0) { return query.OfType<ReturnType>(); }
// Start with a parameter of the type of the query
var parameter = Expression.Parameter(typeof(ReturnType));
// Build up an expression excluding all the sub-types
Expression removeAllSubTypes = null;
foreach (var subType in subTypes) {
// For each sub-type, add a clause to make sure that the parameter is
// not of this type
var removeThisSubType = Expression.Not(Expression
.TypeIs(parameter, subType));
// Merge with the previous expressions
if (removeAllSubTypes == null) {
removeAllSubTypes = removeThisSubType;
} else {
removeAllSubTypes = Expression
.AndAlso(removeAllSubTypes, removeThisSubType);
}
}
// Convert to a lambda (actually pass the parameter in)
var removeAllSubTypesLambda = Expression
.Lambda(removeAllSubTypes, parameter);
// Filter the query
return query
.OfType<ReturnType>()
.Where(removeAllSubTypesLambda as Expression<Func<ReturnType, bool>>);
}
我只在 EF6.1 上使用代码优先模型对其进行了测试。它大量借鉴了Alex James' tip 35 .
关于c# - 从 Entity Framework 中仅检索基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2056092/