如果我将此作为我的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更简单?
答案 0 :(得分:2)
不是Linq to Entities。 Linq to entities提供OfType
但它使用.NET规则进行类型继承,因此如果您使用OfType<Foo>
,您仍然会获得Foo
和Bar
个实例,因为Bar
属于Foo
类型。
实体SQL(在代码中不可用,DbContext API - 您必须通过ObjectContext API访问它)更强大,因为它不依赖于Linq提供的有限功能。它提供的构造OFTYPE ONLY
只能返回Foo
的实例,但我相信它不会使查询更简单,因为要查找哪些类型只有Foo
而不是Bar
它仍然必须加入。如果您希望获得Foo
的实例,即使对象是Bar
,您也无法通过EF实现 - 实体类型是不可变的。您无法在查询中更改类型。
使用OfType
和Linq的最简单的解决方法是将Foo
定义为抽象并添加其他派生类型。您将始终使用OfType
查询实际类型,并确保您没有不必要的表的连接。