我有3个表:用户,角色,投标
其中两个是由ASP.NET Identity创建的,Bids
是我的自定义表(它是Users
表的次要表)
我正在尝试让所有非特定角色的用户(所有非管理员用户)显示出价数量(可以为空 - 我已离开加入),显示每个用户的最高出价并显示出价最高
SQL查询很简单:
SELECT
U.Id
,U.UserName
,U.Email
,ISNULL(MAX(B.PriceInPLN), 0)
,COUNT(B.BidID)
,IIF(MAX(B.PriceInPLN)=(SELECT TOP 1 PriceInPLN FROM Bids B2 (NOLOCK) ORDER BY PriceInPLN DESC),1,0 ) AS Max
FROM
AspNetUsers U ( NOLOCK )
JOIN AspNetUserRoles UR ( NOLOCK ) ON U.Id = UR.UserId
LEFT JOIN Bids B ( NOLOCK ) ON B.ApplicationUserId = U.Id
WHERE
UR.RoleId != '9508f9d2-12fb-4175-89a7-3275cb7616ae'
GROUP BY
U.Id
,U.UserName
,U.Email
但是我无法创建正确的LINQ查询。以下是我到目前为止的情况:
var users =(
from u in db.Users
where !u.Roles.Select(r => r.RoleId).Contains(adminRoleId)//everyone except admins
join b in db.Bids on u equals b.ApplicationUser into ub
from subset in ub.DefaultIfEmpty()//LEFT JOIN
group subset by new { u.Id, u.UserName, u.Email, u.EmailConfirmed, u.Online } into grouped
select new UserReturnModel
{
Id = grouped.Key.Id,
Name = grouped.Key.UserName,
Email = grouped.Key.Email,
EmailConfirmed = grouped.Key.EmailConfirmed,
Online = grouped.Key.Online,
BidsCount = grouped.Count(c => c.ApplicationUserId == grouped.Key.Id),
PriceInPLN = grouped.Max(c => c.PriceInPLN),
IsMax = (grouped.Max(c=>c.PriceInPLN) == db.Bids.Max(b=>b.PriceInPLN))
}).ToList();
我无法让Max列正常工作 - 它总是说真的 以下是列定义,可以轻松显示我想要的内容:
我在ASP.NET中使用它,在调试时我注意到LINQ创建的SQL查询很大:
SELECT
1 AS [C1],
[Project6].[Id] AS [Id],
[Project6].[UserName] AS [UserName],
[Project6].[Email] AS [Email],
[Project6].[EmailConfirmed] AS [EmailConfirmed],
[Project6].[Online] AS [Online],
[Project6].[C4] AS [C2],
[Project6].[C1] AS [C3],
CASE WHEN (([Project6].[C2] = [GroupBy3].[A1]) OR (([Project6].[C2] IS NULL) AND ([GroupBy3].[A1] IS NULL))) THEN cast(1 as bit) WHEN ( NOT (([Project6].[C3] = [GroupBy4].[A1]) AND ((CASE WHEN ([Project6].[C3] IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END) = (CASE WHEN ([GroupBy4].[A1] IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END)))) THEN cast(0 as bit) END AS [C4]
FROM (SELECT
[Project3].[C1] AS [C1],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
[Project3].[Id] AS [Id],
[Project3].[Online] AS [Online],
[Project3].[Email] AS [Email],
[Project3].[EmailConfirmed] AS [EmailConfirmed],
[Project3].[UserName] AS [UserName],
(SELECT
COUNT(1) AS [A1]
FROM ( SELECT
[Extent4].[Id] AS [Id],
[Extent4].[Online] AS [Online],
[Extent4].[Email] AS [Email],
[Extent4].[EmailConfirmed] AS [EmailConfirmed],
[Extent4].[UserName] AS [UserName],
[Extent5].[ApplicationUserId] AS [ApplicationUserId]
FROM [dbo].[AspNetUsers] AS [Extent4]
INNER JOIN [dbo].[Bids] AS [Extent5] ON [Extent5].[ApplicationUserId] = [Extent4].[Id]
WHERE ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AspNetUserRoles] AS [Extent6]
WHERE ([Extent4].[Id] = [Extent6].[UserId]) AND ([Extent6].[RoleId] = @p__linq__0)
)) AND ([Project3].[Id] = [Extent4].[Id]) AND ([Project3].[UserName] = [Extent4].[UserName]) AND (([Project3].[Email] = [Extent4].[Email]) OR (([Project3].[Email] IS NULL) AND ([Extent4].[Email] IS NULL))) AND ([Project3].[EmailConfirmed] = [Extent4].[EmailConfirmed]) AND ([Project3].[Online] = [Extent4].[Online]) AND ([Extent5].[ApplicationUserId] = [Project3].[Id])
) AS [Project5]) AS [C4]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[A2] AS [C2],
[GroupBy1].[A3] AS [C3],
[GroupBy1].[K1] AS [Id],
[GroupBy1].[K2] AS [Online],
[GroupBy1].[K3] AS [Email],
[GroupBy1].[K4] AS [EmailConfirmed],
[GroupBy1].[K5] AS [UserName]
FROM ( SELECT
[Project2].[Id] AS [K1],
[Project2].[Online] AS [K2],
[Project2].[Email] AS [K3],
[Project2].[EmailConfirmed] AS [K4],
[Project2].[UserName] AS [K5],
MAX([Project2].[PriceInPLN]) AS [A1],
MAX([Project2].[PriceInPLN]) AS [A2],
MAX([Project2].[PriceInPLN]) AS [A3]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Online] AS [Online],
[Extent1].[Email] AS [Email],
[Extent1].[EmailConfirmed] AS [EmailConfirmed],
[Extent1].[UserName] AS [UserName],
[Extent2].[PriceInPLN] AS [PriceInPLN],
[Extent2].[ApplicationUserId] AS [ApplicationUserId]
FROM [dbo].[AspNetUsers] AS [Extent1]
LEFT OUTER JOIN [dbo].[Bids] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ApplicationUserId]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AspNetUserRoles] AS [Extent3]
WHERE ([Extent1].[Id] = [Extent3].[UserId]) AND ([Extent3].[RoleId] = @p__linq__0)
)
) AS [Project2]
GROUP BY [Project2].[Id], [Project2].[Online], [Project2].[Email], [Project2].[EmailConfirmed], [Project2].[UserName]
) AS [GroupBy1]
) AS [Project3] ) AS [Project6]
CROSS JOIN (SELECT
MAX([Extent7].[PriceInPLN]) AS [A1]
FROM [dbo].[Bids] AS [Extent7] ) AS [GroupBy3]
CROSS JOIN (SELECT
MAX([Extent8].[PriceInPLN]) AS [A1]
FROM [dbo].[Bids] AS [Extent8] ) AS [GroupBy4]
这可以简化吗?
以下是Entity Framework Power Tools生成的我的数据库模型:
答案 0 :(得分:2)
我不确定为什么你从原始的SQL查询中修改了很多LINQ查询,但是使用我SQL to LINQ Recipe中的规则将SQL查询更接近字面意思
var MaxPriceInPLN = db.Bids.Max(b => b.PriceInPLN);
var ans = from U in db.Users
where !U.Roles.Any(r => r.RoleId == adminRoleId)
join b in db.Bids on U.Id equals b.ApplicationUserId into bj
from b in bj.DefaultIfEmpty()
group new { U, b } by new { U.Id, U.UserName, U.Email } into Ubg
let maxBidPriceInPLN = Ubg.Max(Ub => Ub.b.PriceInPLN)
select new {
Ubg.Key.Id,
Ubg.Key.UserName,
Ubg.Key.Email,
PriceInPLN = maxBidPriceInPLN ?? 0,
BidsCount = Ubg.Count(Ub => Ub.b != null),
IsMax = maxBidPriceInPLN == MaxPriceInPLN
};
您可以使用EF导航属性来隐藏查询中的联接来简化LINQ查询:
var MaxPriceInPLN = db.Bids.Max(b => b.PriceInPLN);
var ans = from U in db.Users
where !U.Roles.Any(r => r.RoleId == adminRoleId)
let maxBidPriceInPLN = U.Bids.Max(b => b.PriceInPLN)
select new {
U.Id,
U.UserName,
U.Email,
PriceInPLN = maxBidPriceInPLN ?? 0,
BidsCount = U.Bids.Count(),
IsMax = maxBidPriceInPLN == MaxPriceInPLN
};