将SQL存储过程转换为Linq。

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

Convert SQL stored procedure to Linq

问题

以下是翻译好的内容:

我创建了以下的存储过程:

PROCEDURE [dbo].[LeadScoring_CountClosedActions]
(@UserId INT,
 @StartDate INT,
 @EndDate INT)
AS
BEGIN
    SET NOCOUNT ON

    SELECT TOP 1 
        COUNT(l.Extra) OVER () AS TotalRecords
	FROM 
        [dbo].[LeadScoringActions] AS a
	INNER JOIN 
        [dbo].[LeadScoringLeads] AS l ON a.LeadId = l.LeadId
    WHERE 
        a.AssignedToUserId = @UserId 
    	AND a.DateCompleted > DATEADD(DAY, @StartDate, GETDATE())
    	AND a.DateCompleted <= DATEADD(DAY, @EndDate, GETDATE())
    	AND a.ActionResultType != 'System Closed'
    	AND l.Extra IS NOT NULL
    GROUP BY 
        l.Extra
END

而我尝试使用以下的EF Core代码来执行它

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

但它总是返回-1,所以我看了一下,似乎我应该将存储过程转换为Linq(参见[此问题的一条评论](https://stackoverflow.com/questions/70822830/ef-6-core-exec-proc-stock-with-count-returning-int))。

我想知道如何做到这一点 - 我知道如何做一般的部分:

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

但我不确定如何做`GROUP BY`部分 - Linq中,它将按`a.Lead.Extra`进行分组,或者是否可以执行`COUNT OVER`?

是将其作为Linq更好,还是有一种执行存储过程并获取正确结果的方法?
英文:

I created the following stored procedure:

PROCEDURE [dbo].[LeadScoring_CountClosedActions]
    (@UserId INT,
	 @StartDate INT,
	 @EndDate INT)
AS
BEGIN
    SET NOCOUNT ON

    SELECT TOP 1 
        COUNT(l.Extra) OVER () AS TotalRecords
	FROM 
        [dbo].[LeadScoringActions] AS a
	INNER JOIN 
        [dbo].[LeadScoringLeads] AS l ON a.LeadId = l.LeadId
	WHERE 
        a.AssignedToUserId = @UserId 
		AND a.DateCompleted > DATEADD(DAY, @StartDate, GETDATE())
		AND a.DateCompleted <= DATEADD(DAY, @EndDate, GETDATE())
		AND a.ActionResultType != 'System Closed'
		AND l.Extra IS NOT NULL
	GROUP BY 
        l.Extra
END

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

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:

var count = await _context
                    .Actions
                    .Include(a => a.Lead)
                    .CountAsync(a => a.ActionResultType != LeadScoringConstants.SystemClosed &&
                                     a.DateCompleted > DateTime.Today.AddDays(request.StartDate) &&
                                     a.DateCompleted <= DateTime.Today.AddDays(request.EndDate) &&
                                     a.AssignedToUserId == userId &&
                                     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解决了这个问题,通过从数据库中获取匹配的操作,然后获取结果中的不同额外属性并计数它们:

var actions = await _context
    .Actions
    .Include(a => a.Lead)
    .Where(a =>
        a.ActionResultType != LeadScoringConstants.SystemClosed &&
        a.DateCompleted > DateTime.Today.AddDays(request.StartDate) &&
        a.DateCompleted <= DateTime.Today.AddDays(request.EndDate) &&
        a.AssignedToUserId == userId &&
        a.Lead.Extra != null)
    .ToListAsync();

var projectIds = actions.Select(a => a.Lead.Extra).Distinct().Count();

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

var count = await _context
    .Actions
    .Where(a =>
        a.ActionResultType != LeadScoringConstants.SystemClosed &&
        a.DateCompleted > DateTime.Today.AddDays(request.StartDate) &&
        a.DateCompleted <= DateTime.Today.AddDays(request.EndDate) &&
        a.AssignedToUserId == userId &&
        a.Lead.Extra != null)
    .Select(a => new { a.Lead.Extra, a.DateCompleted })
    .Distinct()
    .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:

var actions = await _context
                .Actions
                    .Include(a =&gt; a.Lead)
                .Where(a =&gt;
                    a.ActionResultType != LeadScoringConstants.SystemClosed &amp;&amp;
                    a.DateCompleted &gt; DateTime.Today.AddDays(request.StartDate) &amp;&amp;
                    a.DateCompleted &lt;= DateTime.Today.AddDays(request.EndDate) &amp;&amp;
                    a.AssignedToUserId == userId &amp;&amp;
                    a.Lead.Extra != null)
                .ToListAsync();

var projectIds = actions.Select(a =&gt; a.Lead.Extra).Distinct().Count();

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

var count = await _context
    .Actions
    .Where(a =&gt;
        a.ActionResultType != LeadScoringConstants.SystemClosed &amp;&amp;
        a.DateCompleted &gt; DateTime.Today.AddDays(request.StartDate) &amp;&amp;
        a.DateCompleted &lt;= DateTime.Today.AddDays(request.EndDate) &amp;&amp;
        a.AssignedToUserId == userId &amp;&amp;
        a.Lead.Extra != null)
    .Select(a =&gt; new { a.Lead.Extra, a.DateCompleted })
    .Distinct()
    .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:

确定