2017-02-03 20 views
2

私はSQLスクリプトをLinqに変換するための助けが必要です。 2つの大きなテーブルがあります。 ユーザーがどの会社にいるか、ログインしたとき、およびどのアプリケーションに関連しているかについての情報があります。 私が必要とするのは、特定の会社のユーザーのすべてのログイン記録と、ユーザー自身に関する情報です。LINQへのSQLスクリプト

私の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 

は、SQLにLINQで特定のクエリを記述することが可能ですかDapperのようなものが私の唯一の方法だろうか? パフォーマンス上の問題やその他の方法が見つかった場合は、何か助けていただければ幸いです。

+1

http://www.linqpad.net/WhyLINQBeatsSQL.aspx左外部結合を実行し、この –

+0

MSDNを見てみましょう:https://msdn.microsoft.com/en-us/library/bb397895.aspxを –

+0

左結合には 'DefaultIfEmpty'を使用します。あなたが選択したステートメントを入れ子にする理由がありますか?あなたは単に左の結合を行い、 'where'節を追加することはできませんか? – JustLearning

答えて

0

すばらしいコメントをありがとう。 私はあなたの入力に基づいてこのLINQを考え出しました。

var loginRecordsByEmployee = (
from uc in _repository.UserCompanies.FindAll() 
    join ul in _repository.UserLogs.FindAll() on uc.UserId equals ul.UserId into uls 
    from log in uls.Where(u => u.LoginDateTime >= fromDate && u.CompanyId == _user.CompanyId).DefaultIfEmpty() 
where uc.Enabled && uc.CompanyId == _user.CompanyId 
select new 
{ 
    uc.EmployeeId, 
    uc.LastLoggedOn, 
    uc.ICalLastAccessedOn, 
    ApplicationTypeId = log == null ? 0 : log.ApplicationTypeId, 
    Success = log != null && log.Success.HasValue && log.Success.Value ? 1 : 0, 
    HasLog = log != null 
}).ToList(); 

このクエリでは、結果として適切なパフォーマンスが得られます。

exec sp_executesql N'SELECT 
1 AS [C1], 
[Extent1].[EmployeeId] AS [EmployeeId], 
[Extent1].[LastLoggedOn] AS [LastLoggedOn], 
[Extent1].[ICalLastAccessedOn] AS [ICalLastAccessedOn], 
CASE WHEN ([Extent2].[UserLogId] IS NULL) THEN 0 ELSE [Extent2].[ApplicationTypeId] END AS [C2], 
CASE WHEN (([Extent2].[UserLogId] IS NOT NULL) AND ([Extent2].[Success] IS NOT NULL) AND ([Extent2].[Success] = 1)) THEN 1 ELSE 0 END AS [C3], 
CASE WHEN ([Extent2].[UserLogId] IS NOT NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C4] 
FROM [dbo].[UserCompany] AS [Extent1] 
LEFT OUTER JOIN [dbo].[UserLog] AS [Extent2] ON ([Extent1].[UserId] = [Extent2].[UserId]) AND ([Extent2].[LoginDateTime] >= @p__linq__0) AND ([Extent2].[CompanyId] = @p__linq__1) 
WHERE ([Extent1].[Enabled] = 1) AND ([Extent1].[CompanyId] = @p__linq__2)',N'@p__linq__0 datetime2(7),@p__linq__1 uniqueidentifier,@p__linq__2 uniqueidentifier',@p__linq__0='2017-01-04 00:00:00',@p__linq__1='EF9DB139-1C72-452F-BE88-6315E44DC2ED',@p__linq__2='EF9DB139-1C72-452F-BE88-6315E44DC2ED' 
関連する問題