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");
}

ただし、ご想像のとおり、基本クラスに対するこの種のクエリは、SQLServerが処理する悪夢のようなクエリにすぐにつながる可能性があります。したがって、質問。

LinqにEF5.0に、派生型ではなく基本型のみを戻す必要があることを通知することは可能ですか。したがって、最終的なSQLをはるかに簡単にしますか?

4

1 に答える 1

2

LinqtoEntitiesではありません。エンティティへのLinqは提供しますOfTypeが、型の継承に.NETルールを使用するため、使用する場合でも、型がであるため、インスタンスとインスタンスのOfType<Foo>両方を取得できます。FooBarBarFoo

エンティティSQL(コードファーストおよびDbContext APIでは使用できません。ObjectContextAPIを介してアクセスする必要があります)は、Linqが提供する制限された機能に依存しないため、より強力です。OFTYPE ONLYのインスタンスのみを返すことができる構造を提供しますが、どのタイプが唯一であり、まだ結合する必要がないFooかを見つけるため、クエリが単純になることはないと思います。オブジェクトがである場合でものインスタンスを取得することを期待している場合、 EFではそれを達成できません-エンティティタイプは不変です。クエリのタイプを変更することはできません。FooBarFooBar

使用する最も簡単な回避策OfTypeとLinqはFoo、抽象として定義し、派生型を追加することです。常に実際の型をクエリし、OfType不要なテーブルとの結合がないことを確認する必要があります。

于 2012-12-13T09:26:24.800 に答える