【发布时间】:2011-07-27 17:28:33
【问题描述】:
我有两个实体,用户和用户权限。 User 实体包含您所有的普通字段,Id、Username、Email 等,而 UserPermission 实体有两个值,UserId 和 PermissionId。我编写了一个存储库方法 GetUserWithPermissions,它最初使用了 Include 扩展并做了这样的事情:
return dbContext.Users.Include(u => u.UserPermission).Where(u => u.Username.Equals(username)).FirstOrDefault();
它很好用,但问题是会有一堆与任何给定用户关联的 UserPermission 实体,并且使用 Include 扩展基本上只是将两个表扁平化为一个,因此所有用户字段都针对每一个重复与用户关联的用户权限。返回的数据如下所示:
Id Username Email ... PermissionId
1 johndoe john@email.com 1
1 johndoe john@email.com 2
1 johndoe john@email.com 3
1 johndoe john@email.com 4
1 johndoe john@email.com 5
1 johndoe john@email.com 6
1 johndoe john@email.com 7
每行之间的唯一区别是最后一列 PermissionId。如果我们为用户定义了 50 个权限,那么当我认为没有必要时,就会返回大量重复数据。显然我的另一个选择是做这样的事情:
User user = dbContext.Users.Where(u => u.Username.Equals(username)).FirstOrDefault();
if (user != null)
user.UserPermissions.ToList();
return user;
上面的代码完成了同样的事情,返回的数据大大减少,但权衡的是两次访问数据库。
哪种方法更好?返回大量重复数据或两次访问数据库?
这是由实体框架生成的 SQL 查询
SELECT
[Project2].[Id] AS [Id],
[Project2].[Username] AS [Username],
[Project2].[LoweredUsername] AS [LoweredUsername],
[Project2].[CompanyId] AS [CompanyId],
[Project2].[FirstName] AS [FirstName],
[Project2].[LastName] AS [LastName],
[Project2].[Email] AS [Email],
[Project2].[C1] AS [C1],
[Project2].[UserId] AS [UserId],
[Project2].[PermissionValue] AS [PermissionValue]
FROM ( SELECT
[Limit1].[Id] AS [Id],
[Limit1].[Username] AS [Username],
[Limit1].[LoweredUsername] AS [LoweredUsername],
[Limit1].[CompanyId] AS [CompanyId],
[Limit1].[FirstName] AS [FirstName],
[Limit1].[LastName] AS [LastName],
[Limit1].[Email] AS [Email],
[Extent2].[UserId] AS [UserId],
[Extent2].[PermissionValue] AS [PermissionValue],
CASE WHEN ([Extent2].[PermissionValue] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM (SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Username] AS [Username],
[Extent1].[LoweredUsername] AS [LoweredUsername],
[Extent1].[CompanyId] AS [CompanyId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Email] AS [Email]
FROM [dbo].[Users] AS [Extent1]
WHERE [Extent1].[LoweredUsername] = (LOWER(LTRIM(RTRIM(@p__linq__0)))) ) AS [Limit1]
LEFT OUTER JOIN [dbo].[UserPermissions] AS [Extent2] ON [Limit1].[Id] = [Extent2].[UserId]
) AS [Project2]
ORDER BY [Project2].[Id] ASC, [Project2].[C1] ASC
谢谢
尼克
【问题讨论】:
-
看起来我误解了你的问题 - 我认为这是关于优化,你的两种方法的结果都是一样的。
-
@BrokenGlass 所以你的意思是在一次数据库调用中返回一堆重复数据与在两次数据库调用中返回更少的数据是一样的?
-
否 - 生成的
User实体相同,性能可能不同。
标签: entity-framework include code-first