将SQL存储过程转换为Linq。

huangapple go评论123阅读模式
英文:

Convert SQL stored procedure to Linq

问题

以下是翻译好的内容:

  1. 我创建了以下的存储过程:
  2. PROCEDURE [dbo].[LeadScoring_CountClosedActions]
  3. (@UserId INT,
  4. @StartDate INT,
  5. @EndDate INT)
  6. AS
  7. BEGIN
  8. SET NOCOUNT ON
  9. SELECT TOP 1
  10. COUNT(l.Extra) OVER () AS TotalRecords
  11. FROM
  12. [dbo].[LeadScoringActions] AS a
  13. INNER JOIN
  14. [dbo].[LeadScoringLeads] AS l ON a.LeadId = l.LeadId
  15. WHERE
  16. a.AssignedToUserId = @UserId
  17. AND a.DateCompleted > DATEADD(DAY, @StartDate, GETDATE())
  18. AND a.DateCompleted <= DATEADD(DAY, @EndDate, GETDATE())
  19. AND a.ActionResultType != 'System Closed'
  20. AND l.Extra IS NOT NULL
  21. GROUP BY
  22. l.Extra
  23. END
  24. 而我尝试使用以下的EF Core代码来执行它
  25. var count = await _context.Database.ExecuteSqlRawAsync($"exec LeadScoring_CountClosedActions @UserId={userId}, @StartDate={request.StartDate}, @EndDate={request.EndDate}");
  26. 但它总是返回-1,所以我看了一下,似乎我应该将存储过程转换为Linq(参见[此问题的一条评论](https://stackoverflow.com/questions/70822830/ef-6-core-exec-proc-stock-with-count-returning-int))。
  27. 我想知道如何做到这一点 - 我知道如何做一般的部分:
  28. var count = await _context
  29. .Actions
  30. .Include(a => a.Lead)
  31. .CountAsync(a => a.ActionResultType != LeadScoringConstants.SystemClosed &&
  32. a.DateCompleted > DateTime.Today.AddDays(request.StartDate) &&
  33. a.DateCompleted <= DateTime.Today.AddDays(request.EndDate) &&
  34. a.AssignedToUserId == userId &&
  35. a.Lead.Extra != null);
  36. 但我不确定如何做`GROUP BY`部分 - Linq,它将按`a.Lead.Extra`进行分组,或者是否可以执行`COUNT OVER`
  37. 是将其作为Linq更好,还是有一种执行存储过程并获取正确结果的方法?
英文:

I created the following stored procedure:

  1. PROCEDURE [dbo].[LeadScoring_CountClosedActions]
  2. (@UserId INT,
  3. @StartDate INT,
  4. @EndDate INT)
  5. AS
  6. BEGIN
  7. SET NOCOUNT ON
  8. SELECT TOP 1
  9. COUNT(l.Extra) OVER () AS TotalRecords
  10. FROM
  11. [dbo].[LeadScoringActions] AS a
  12. INNER JOIN
  13. [dbo].[LeadScoringLeads] AS l ON a.LeadId = l.LeadId
  14. WHERE
  15. a.AssignedToUserId = @UserId
  16. AND a.DateCompleted > DATEADD(DAY, @StartDate, GETDATE())
  17. AND a.DateCompleted <= DATEADD(DAY, @EndDate, GETDATE())
  18. AND a.ActionResultType != 'System Closed'
  19. AND l.Extra IS NOT NULL
  20. GROUP BY
  21. l.Extra
  22. END

And I was trying to execute it with the following in EF Core:

  1. var count = await _context.Database.ExecuteSqlRawAsync($"exec LeadScoring_CountClosedActions @UserId={userId}, @StartDate={request.StartDate}, @EndDate={request.EndDate}");

But it was always returning -1 so I had a look around and it would seem I should convert the stored procedure to Linq (see one of the comments on this question)

I was wondering how I would do that - I know how to do the general bits:

  1. var count = await _context
  2. .Actions
  3. .Include(a => a.Lead)
  4. .CountAsync(a => a.ActionResultType != LeadScoringConstants.SystemClosed &&
  5. a.DateCompleted > DateTime.Today.AddDays(request.StartDate) &&
  6. a.DateCompleted <= DateTime.Today.AddDays(request.EndDate) &&
  7. a.AssignedToUserId == userId &&
  8. a.Lead.Extra != null);

But I'm not sure how to do the GROUP BY - in the linq, it would be grouped by a.Lead.Extra or if it's possible to do a COUNT OVER?

Is it better to do it as linq or is there a way to execute the stored procedure and get the correct result?

答案1

得分: 0

最终,我使用LINQ解决了这个问题,通过从数据库中获取匹配的操作,然后获取结果中的不同额外属性并计数它们:

  1. var actions = await _context
  2. .Actions
  3. .Include(a => a.Lead)
  4. .Where(a =>
  5. a.ActionResultType != LeadScoringConstants.SystemClosed &&
  6. a.DateCompleted > DateTime.Today.AddDays(request.StartDate) &&
  7. a.DateCompleted <= DateTime.Today.AddDays(request.EndDate) &&
  8. a.AssignedToUserId == userId &&
  9. a.Lead.Extra != null)
  10. .ToListAsync();
  11. var projectIds = actions.Select(a => a.Lead.Extra).Distinct().Count();

根据评论,我可以将其更改为LINQ:

  1. var count = await _context
  2. .Actions
  3. .Where(a =>
  4. a.ActionResultType != LeadScoringConstants.SystemClosed &&
  5. a.DateCompleted > DateTime.Today.AddDays(request.StartDate) &&
  6. a.DateCompleted <= DateTime.Today.AddDays(request.EndDate) &&
  7. a.AssignedToUserId == userId &&
  8. a.Lead.Extra != null)
  9. .Select(a => new { a.Lead.Extra, a.DateCompleted })
  10. .Distinct()
  11. .CountAsync();
英文:

In the end I solved it using linq by getting the matching actions from the db then I got the distinct extra properties from the results and counted them:

  1. var actions = await _context
  2. .Actions
  3. .Include(a =&gt; a.Lead)
  4. .Where(a =&gt;
  5. a.ActionResultType != LeadScoringConstants.SystemClosed &amp;&amp;
  6. a.DateCompleted &gt; DateTime.Today.AddDays(request.StartDate) &amp;&amp;
  7. a.DateCompleted &lt;= DateTime.Today.AddDays(request.EndDate) &amp;&amp;
  8. a.AssignedToUserId == userId &amp;&amp;
  9. a.Lead.Extra != null)
  10. .ToListAsync();
  11. var projectIds = actions.Select(a =&gt; a.Lead.Extra).Distinct().Count();

As per comments, I can change this to be done in linq:

  1. var count = await _context
  2. .Actions
  3. .Where(a =&gt;
  4. a.ActionResultType != LeadScoringConstants.SystemClosed &amp;&amp;
  5. a.DateCompleted &gt; DateTime.Today.AddDays(request.StartDate) &amp;&amp;
  6. a.DateCompleted &lt;= DateTime.Today.AddDays(request.EndDate) &amp;&amp;
  7. a.AssignedToUserId == userId &amp;&amp;
  8. a.Lead.Extra != null)
  9. .Select(a =&gt; new { a.Lead.Extra, a.DateCompleted })
  10. .Distinct()
  11. .CountAsync();

huangapple
  • 本文由 发表于 2023年8月4日 20:42:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76836023.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定