Следует ли использовать агрегированные корневые репозитории DDD с EF 4.1 + LINQ?

Я читал DDD Evans, и я экспериментирую с дизайном совокупного корневого репозитория с использованием C # и Entity Framework 4.1 + LINQ.

Однако меня беспокоят фактические запросы, которые отправляются в БД. Я использую SQL 2008 R2 и запускаю SQL Profiler, чтобы проверить, что делает БД в ответ на код LINQ.

Рассмотрим простой дизайн из двух сущностей с Person и EmailAddress. Один человек может иметь от нуля до нескольких адресов электронной почты, а адрес электронной почты должен иметь ровно одно лицо. 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 Profiler:

SELECT 
[Extent1].[Id] AS [Id],  
[Extent1].[FirstName] AS [FirstName],  
[Extent1].[LastName] AS [LastName], 
FROM [dbo].[Person] AS [Extent1]

В дополнение к вышеупомянутому запросу, который выбирает из Person, существует ряд событий «RPC: Completed», по одному для каждой строки EmailAddress в базе данных:

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

Моя тестовая база данных имеет 14 строк в dbo.EmailAddress, и есть 14 различных вызовов RPC: Completed, каждый с другим значением @ EntityKeyValue1.

Я предполагаю, что это плохо для производительности SQL, так как dbo Таблица .EmailAddress получает больше строк, больше этих RPC будет вызываться в базе данных. Есть ли другой лучший подход к использованию совокупных корневых репозиториев DDD с EF 4.1 + LINQ?

Обновление: Решено

Проблема заключалась в том, что свойство All возвращало IEnumerable . После того, как это было изменено на IQueryable , LINQ включился и выбрал все лицо + электронные письма за один раз. Однако мне пришлось связать .Include (p => p.Emails), прежде чем возвращать IQueryable из All.

5
задан danludwig 18 May 2011 в 19:27
поделиться