【发布时间】:2017-06-20 19:11:09
【问题描述】:
在将 SQL 脚本转换为 Linq 时,我需要一些帮助。 有2张大桌子。 一个包含用户所在公司的信息。另一个包含用户登录时间和应用程序的信息。 我需要的是特定公司用户的所有登录记录以及有关用户本身的一些信息。
我的 SQL 查询看起来像这样,并且执行得非常好。
SELECT
UserLog.[ApplicationTypeId] AS [ApplicationTypeId],
UserCompany.[EmployeeId] AS [EmployeeId],
UserCompany.[LastLoggedOn] AS [LastLoggedOn],
UserCompany.[ICalLastAccessedOn] AS [ICalLastAccessedOn],
CASE WHEN ((UserLog.[Success] IS NOT NULL) AND (UserLog.[Success] = 1)) THEN 1 ELSE 0 END AS [C1]
FROM
(select Enabled, CompanyId, EmployeeId, Userid, LastLoggedOn, ICalLastAccessedOn from UserCompany WHERE [Enabled] = 1 AND CompanyId = CompanyId) AS UserCompany
LEFT JOIN
(select * from [dbo].[UserLog] AS [Extent2] where [Extent2].[LoginDateTime] >= '2017-01-04 00:00:00' and [CompanyId] = CompanyId) as UserLog
ON UserCompany.[UserId] = UserLog.[UserId]
我在 C# 上的尝试看起来像这样,而且性能很差。
var loginRecordsByEmployee = (
from uc in
(from userCompany in _repository.UserCompanies.FindAll()
where userCompany.Enabled && userCompany.CompanyId == _user.CompanyId
select new { userCompany.EmployeeId, userCompany.LastLoggedOn, userCompany.ICalLastAccessedOn, userCompany.UserId })
join ul in
(from log in _repository.UserLogs.FindAll()
where log.LoginDateTime >= fromDate && log.CompanyId == _user.CompanyId
select new { log.UserId , log.ApplicationTypeId, log.Success})
on uc.UserId equals ul.UserId
select new
{
uc.EmployeeId,
uc.LastLoggedOn,
uc.ICalLastAccessedOn,
ul.ApplicationTypeId,
Success = ul.Success.HasValue && ul.Success.Value ? 1 : 0
}).ToList();
查询实体框架生成的是使用 INNER JOIN 并在连接后添加 WHERE,而不是过滤每个选择。
exec sp_executesql N'SELECT
[Extent2].[ApplicationTypeId] AS [ApplicationTypeId],
[Extent1].[EmployeeId] AS [EmployeeId],
[Extent1].[LastLoggedOn] AS [LastLoggedOn],
[Extent1].[ICalLastAccessedOn] AS [ICalLastAccessedOn],
CASE WHEN (([Extent2].[Success] IS NOT NULL) AND ([Extent2].[Success] = 1)) THEN 1 ELSE 0 END AS [C1]
FROM [dbo].[UserCompany] AS [Extent1]
INNER JOIN [dbo].[UserLog] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[UserId]
WHERE ([Extent1].[Enabled] = 1) AND ([Extent1].[CompanyId] = @p__linq__0) AND ([Extent2].[LoginDateTime] >= @p__linq__1) AND ([Extent2].[CompanyId] = @p__linq__2)',N'@p__linq__0 uniqueidentifier,@p__linq__1 datetime2(7),@p__linq__2 uniqueidentifier',@p__linq__0='EF9DB139-1C72-452F-BE88-6315E44DC2ED',@p__linq__1='2017-01-04 00:00:00',@p__linq__2=CompanyId
是否可以在 LINQ to SQL 中编写特定查询,或者像 Dapper 这样的东西是我唯一的方法吗? 如果您碰巧发现任何性能问题或其他方法,我们将不胜感激并随时提供帮助。
【问题讨论】:
-
MSDN 执行左外连接:msdn.microsoft.com/en-us/library/bb397895.aspx
-
如果您想要左连接,请使用
DefaultIfEmpty。在加入它们之前嵌套选择语句是否有原因。你能不能简单地做左连接并添加你的where子句 -
这样的事情应该可以解决问题:
(from uCompany in _repository.UserCompanies from uLog in _repository.UserLogs.Where(x=>x.UserId==uCompany.UserId).DefaultIfEmpty() where .. select new {...}).ToList(); -
仅了解基本 SQL 的人撰写的“为什么 linq 胜过 sql”的文章。那篇文章有一些好的观点,但很多都没有抓住重点或对语言的理解不完整
标签: c# sql performance entity-framework linq