我读过DDD Evans,并且正在使用C#和Entity Framework 4.1 + LINQ试验一个聚合根存储库设计。我应该在EF 4.1 + LINQ中使用DDD聚合根存储库吗?
但是,我担心发送到数据库的实际查询。我正在使用SQL 2008 R2,并运行SQL事件探查器来检查数据库响应LINQ代码所做的事情。
考虑使用Person和EmailAddress的简单2实体设计。一个人可以有零到多个EmailAddress,而一个EmailAddress只能有一个Person。 Person是聚合根,因此不应该有电子邮件地址的存储库。电子邮件地址应该从Person存储库中选出(根据DDD Evans)。
为了比较,我确实为电子邮件地址设置了一个临时存储库。下面的代码行:
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 emailString = "[email protected]";
var emailEntity = _tempEmailRepository.All.SingleOrDefault(e =>
e.Value.Equals(emailString, StringComparison.OrdinalIgnoreCase));
...根据探查执行一个干净的SQL查询:
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]
除了从人选择上面的查询,有许多的“RPC:已完成”事件,一个用于在DB每个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:已完成的调用,每个都有不同的@ EntityKeyValue1值。
我假设这对SQL性能不利,因为dbo.EmailAddress表获得更多行,更多的这些RPC将在db上调用。在EF 4.1 + LINQ中使用DDD聚合根存储库还有另一种更好的方法吗?
更新:解决
的问题是,所有的财产返回一个IEnumerable<TEntity>
。在这改为IQueryable<TEntity>
之后,LINQ一下子就进入并选择了整个Person + Emails。但是,我必须链接.Include(p => p.Emails)才能从All返回IQueryable。
你从'All'属性返回什么? – 2011-05-18 15:26:36
好问题。当我发布这个所有返回一个IEnumerable。将其更改为IQueryable并查看其差异。将发布更新。 –
danludwig
2011-05-18 19:23:17