Search code examples
sqllinqlinq-to-entities

Replicate SQL result in Linq


I have a simple view:

CREATE VIEW [dbo].[ApplicationSummary]
AS
    SELECT 
        CONVERT(VARCHAR(50), NEWID()) AS ID,
        ISNULL(AVG(ApplicationTime), 0) AS 'AvgApplicationTime',
        ISNULL(AVG(ResponseTime), 0) AS 'AvgResponseTime',
        ISNULL(CAST(1.0 * COUNT(CASE WHEN [IsAccepted] = 1 THEN 1 END) / COUNT(*) AS float), 0) AS 'PctAccepted'
    FROM 
        [Application]
    WHERE 
        (IsValid = 1) 
        AND (CreatedOn < CAST(GETDATE() AS date) 
        AND CreatedOn >= CAST(GETDATE()-30 AS date))

The idea is that it outputs 3 variables. The first 2 are simple 'averages', whereas the last one, 'PctAccepted' outputs a ratio.

I'm testing a table containing 4 rows — 3 of them are set to IsAccepted = true, so the result is 0.75 (3/4), which converts to 75%.

I'm trying to remove the need for a view and replicate it using Linq over my Entity Framework class.

Here is the important stuff from the query:

var startDate = DateTime.Today;
var endDate = DateTime.Today.AddDays(-30);

var q = r.Find(x => x.IsValid &&
                    x.CreatedOn < startDate && x.CreatedOn >= endDate)
         .GroupBy(x => x)
         .Select(g => new
            {
                AvgApplicationTime = (int)g.Average(i => i.ApplicationTime),
                AvgResponseTime = (int)g.Average(i => i.ResponseTime),
                ApprovalRatio = g.Count(i => i.IsAccepted == true) / (double)g.Count()
            }).First();

return new ApplicationStats(q.AvgApplicationTime, q.AvgResponseTime, q.ApprovalRatio);

So far, I have the two averages outputting correctly, but the ratio is returning 1 (or 100%).

Initially, I thought it may be a rounding issue but I've outputted the result of this line: g.Count(i => i.IsAccepted == true) and it incorrectly returns 1.

I may have grouping in the wrong place, but am currently struggling to make it work.

Any help appreciated.


Solution

  • Found the answer.

    Changed .GroupBy(x => x) to .GroupBy(x => 1).

    Also g.Count(i => i.IsAccepted == true) can be simplified to g.Count(i => i.IsAccepted)