DDD Evansを読み、C#とEntity Framework 4.1+LINQを使用して集約ルートリポジトリの設計を実験しています。
ただし、DBに送信される実際のクエリが心配です。私はSQL2008R2を使用しており、SQL Profilerを実行して、LINQコードに応答してDBが何を行っているかを調べています。
PersonとEmailAddressを使用した単純な2エンティティの設計について考えてみます。1人の人は0から多数のEmailAddressesを持つことができ、EmailAddressは正確に1人の人を持つ必要があります。Personは集約ルートであるため、電子メールアドレスのリポジトリは存在しないはずです。電子メールアドレスは、Personリポジトリから選択する必要があります(DDD Evansによる)。
比較のために、メールアドレス用に一時的なリポジトリを設定しています。次のコード行:
var emailString = "someone@somewhere.com";
var emailEntity = _tempEmailRepository.All.SingleOrDefault(e =>
e.Value.Equals(emailString, StringComparison.OrdinalIgnoreCase));
...プロファイラーに従ってクリーンなSQLクエリを実行します。
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[PersonId] AS [PersonId],
[Extent1].[Value] AS [Value],
[Extent1].[IsDefault] AS [IsDefault],
[Extent1].[IsConfirmed] AS [IsConfirmed],
FROM [dbo].[EmailAddress] AS [Extent1]
次のコードを使用して、個人リポジトリから電子メールを選択できます。
var emailEntity = _personRepository.All.SelectMany(p => p.Emails)
.SingleOrDefault(e => e.Value.Equals(emailString,
StringComparison.OrdinalIgnoreCase))
これにより、実行時に同じエンティティが取得されますが、SQLプロファイラーに異なるコマンドが表示されます。
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
FROM [dbo].[Person] AS [Extent1]
Personから選択する上記のクエリに加えて、DBのEmailAddress行ごとに1つずつ、多数の「RPC:Completed」イベントがあります。
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
[Extent1].[PersonId] AS [PersonId],
[Extent1].[Value] AS [Value],
[Extent1].[IsDefault] AS [IsDefault],
[Extent1].[IsConfirmed] AS [IsConfirmed],
FROM [dbo].[EmailAddress] AS [Extent1]
WHERE [Extent1].[PersonId] =
@EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
[Extent1].[PersonId] AS [PersonId],
[Extent1].[Value] AS [Value],
[Extent1].[IsDefault] AS [IsDefault],
[Extent1].[IsConfirmed] AS [IsConfirmed],
FROM [dbo].[EmailAddress] AS [Extent1]
WHERE [Extent1].[PersonId] =
@EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=2
私のテストデータベースにはdbo.EmailAddressに14行あり、14個の異なるRPC:Completed呼び出しがあり、それぞれが異なる@EntityKeyValue1値を持っています。
dbo.EmailAddressテーブルがより多くの行を取得すると、これらのRPCの多くがデータベースで呼び出されるため、これはSQLのパフォーマンスに悪いと思います。EF 4.1 + LINQでDDD集約ルートリポジトリを使用するための別のより良いアプローチはありますか?
更新:解決済み
問題は、Allプロパティがを返していたことでしたIEnumerable<TEntity>
。これがに変更された後IQueryable<TEntity>
、LINQが起動し、Person+Email全体を一度に選択しました。ただし、AllからIQueryableを返す前に、.Include(p => p.Emails)をチェーンする必要がありました。