c# - 从 Entity Framework 中仅检索基类

标签 c# entity-framework linq-to-entities entity-framework-4

如果我在 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/

相关文章:

c# - 为什么不允许从 "class A : IX"到通用 "T where T : IX"的转换?

c# - 在 SignalR 2.0 OnReceived 处理程序中调用 await 的正确方法

c# - 如何在单元测试中调用Postsharp Aspect?

sql - Entity Framework 返回与 SSMS 不同的结果

c# - 同步对 ASP.NET session 成员的访问

c# - 创建模型时无法使用上下文

c# - 是否有可能在将其保存在 Entity Framework 之前获取身份字段值

c# - 为什么 LINQ-to-Entities 将此查询放在子选择中?

c# - Linq-to-Entities 中的 IDENT_CURRENT

c# - 选择对象的子子项