Linq 2 SQL を使用してサンプル アプリケーションに AdventureWorks db を実装しているときに、DBML で定義された継承マッピングで Linq 2 SQL が派生型の SQL ステートメントを生成する方法に問題がありました。
DBML に Person と PersonPhone (1 つの Person から多数の PersonPhone へ) という 2 つのエンティティがあり、継承マッピングは定義されていません (Person は後の例で継承基本クラスになります)。次に、次の Linq ステートメントを実行すると、トレースの実行中に次の SQL が期待どおりに生成されることに気付きます。
void Main()
{
this.DeferredLoadingEnabled = false;
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Person>(n => n.PersonPhones);
this.LoadOptions = dlo;
Person person = this.Persons.SingleOrDefault(n => n.BusinessEntityID == 291);
person.PersonPhones.Dump();
}
DECLARE @p0 Int = 291
SELECT [t0].[BusinessEntityID], [t0].[PersonType], [t0].[NameStyle], [t0].[Title], [t0].[FirstName], [t0].[MiddleName], [t0].[LastName], [t0].[Suffix], [t0].[EmailPromotion], [t0].[AdditionalContactInfo], [t0].[Demographics], [t0].[rowguid], [t0].[ModifiedDate], [t1].[BusinessEntityID] AS [BusinessEntityID2], [t1].[PhoneNumber], [t1].[PhoneNumberTypeID], [t1].[ModifiedDate] AS [ModifiedDate2], (
SELECT COUNT(*)
FROM [Person].[PersonPhone] AS [t2]
WHERE [t2].[BusinessEntityID] = [t0].[BusinessEntityID]
) AS [value]
FROM [Person].[Person] AS [t0]
LEFT OUTER JOIN [Person].[PersonPhone] AS [t1] ON [t1].[BusinessEntityID] = [t0].[BusinessEntityID]
WHERE [t0].[BusinessEntityID] = @p0
ORDER BY [t0].[BusinessEntityID], [t1].[PhoneNumber], [t1].[PhoneNumberTypeID]
その結果、SQL は単一のステートメントで生成されます。これは非効率的な SQL である可能性があるという事実を無視してください。私が指摘しているのは、単一のステートメントで実行されたということです。
しかし、DBML に継承マッピング情報を含め、StoreContact (Person から派生) という新しいエンティティ タイプを定義し、まったく同じクエリを実行すると、実際には以下に示すように異なる結果が得られます。その中で、2 つの SQL ステートメントが実際に実行されます。
DECLARE @p0 Int = 291
SELECT [t0].[PersonType], [t0].[BusinessEntityID], [t0].[NameStyle], [t0].[Title], [t0].[FirstName], [t0].[MiddleName], [t0].[LastName], [t0].[Suffix], [t0].[EmailPromotion], [t0].[AdditionalContactInfo], [t0].[Demographics], [t0].[rowguid], [t0].[ModifiedDate]
FROM [Person].[Person] AS [t0]
WHERE [t0].[BusinessEntityID] = @p0
GO
DECLARE @x1 Int = 291
SELECT [t0].[BusinessEntityID], [t0].[PhoneNumber], [t0].[PhoneNumberTypeID], [t0].[ModifiedDate]
FROM [Person].[PersonPhone] AS [t0]
WHERE [t0].[BusinessEntityID] = @x1
これは、継承機能を実装する場合にDBへの重複呼び出しを行うためにLinq 2 SQLが必要であるという点で、アプリケーションの速度をかなり大幅に低下させるという点で、多少問題があります. OOP モデルにはコストがかかるようです。
この問題を回避して、SQL を単一のステートメントで実行する方法はありますか?