2

如果我有这个作为我的 TPT 模型:

public class Foo
{
    public Int32 Id { get; set; }
    public string Text { get; set;  }
}

[Table("Bars")]
public class Bar : Foo
{
    public string MoreText { get; set; }
}

和这样的派生 DbContext:

public class MyContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Bar> Bars { get; set; }
}

然后,当我对 Foo 执行查询时,最终的 SQL 将包含到 Bar 的外部连接。

例如:

uisng(var context = new MyContext())
{
    Console.WriteLine(context.Foos.ToString());
}

将导致这作为最终的 SQL 语句

SELECT
CASE WHEN ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) THEN
'0X' ELSE '0X0X' END AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Text] AS [Text],
CASE WHEN ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) THEN
CAST(NULL AS varchar(1)) ELSE [Project1].[MoreText] END AS [C2]
FROM  [dbo].[Foos] AS [Extent1]
LEFT OUTER JOIN  (SELECT
        [Extent2].[Id] AS [Id],
        [Extent2].[MoreText] AS [MoreText],
        cast(1 as bit) AS [C1]
        FROM [dbo].[Bars] AS [Extent2] ) AS [Project1] ON [Extent1].[Id] = [Proj
ect1].[Id]

我确实理解为什么 --- 这样做可以让我做类似的事情:

foreach(var x in context.Foos)
{
    if(x is Bar) Console.WriteLine("Impressive");
    else Console.WriteLine("Not so much");
}

但是,正如您可以想象的那样,这种对基类的查询会很快导致 SQL Server 处理的噩梦般的查询。因此问题。

是否可以通知 Linq 到 EF 5.0 它应该只带回基本类型而不是派生类型。因此使最终的 SQL 更简单?

4

1 回答 1

2

不适用于 Linq to Entity。Linq to entity 提供OfType,但它使用 .NET 规则进行类型继承,因此如果您使用OfType<Foo>,您仍然会同时获得FooBar实例,因为Bar它属于 .NET 类型Foo

实体 SQL(在代码优先和 DbContext API 中不可用 - 您必须通过 ObjectContext API 访问它)更强大,因为它不依赖于 Linq 提供的有限功能。它提供OFTYPE ONLY了只能返回实例的构造,Foo但我相信它不会使查询更简单,因为要找到哪些类型是唯一的Foo,而不是Bar它仍然必须进行连接。如果您希望获得的实例Foo即使对象是Bar您也无法使用 EF 实现 - 实体类型是不可变的。您不能更改查询中的类型。

使用和 Linq 最简单的解决方法OfType是定义Foo为抽象并添加额外的派生类型。您将始终查询一个真实类型,OfType并且它应该确保您没有与不必要的表的连接。

于 2012-12-13T09:26:24.800 回答