3

Is clean (or should I say performant) SQL achievable in Linq to Sql?

I wanted the Linq to Sql produce this code:

SELECT C.CustomerID, COUNT(O.CustomerID) AS N
FROM Customers C
LEFT JOIN Orders O ON O.CustomerID = C.CustomerID
GROUP BY C.CustomerID

And I follow this code: LINQ - Left Join, Group By, and Count

So here's my version of code:

var q = from c in db.Customers
        join o in db.Orders on c.CustomerID equals o.CustomerID into sr
        from x in sr.DefaultIfEmpty()
        group x by c.CustomerID into y
        select new { y.Key, N = y.Count(t => t.CustomerID != null) };

But it generate this...

SELECT [t2].[CustomerID] AS [Key], (
    SELECT COUNT(*)
    FROM [Customers] AS [t3]
    LEFT OUTER JOIN [Orders] AS [t4] ON [t3].[CustomerID] = [t4].[CustomerID]
    WHERE ([t4].[CustomerID] IS NOT NULL) AND ((([t2].[CustomerID] IS NULL) AND ([t3].[CustomerID] IS NULL)) OR (([t2].[CustomerID] IS NOT NULL) AND ([t3].[CustomerID] IS NOT NULL) AND ([t2].[CustomerID] = [t3].[CustomerID])))
    ) AS [N]
FROM (
    SELECT [t0].[CustomerID]
    FROM [Customers] AS [t0]
    LEFT OUTER JOIN [Orders] AS [t1] ON [t0].[CustomerID] = [t1].[CustomerID]
    GROUP BY [t0].[CustomerID]
    ) AS [t2]

...Which I find unacceptable.

Then I try this...

var q = from c in db.Customers
        join o in db.Orders on c.CustomerID equals o.CustomerID into sr
        from x in sr.DefaultIfEmpty()
        group x by c.CustomerID into y                                        
        select new { y.Key, N = y.Sum(t => t.CustomerID != null ? 1 : 0 )};

...and here is the resulting query:

SELECT SUM(
    (CASE
        WHEN [t1].[CustomerID] IS NOT NULL THEN @p0
        ELSE @p1
     END)) AS [N], [t0].[CustomerID] AS [Key]
FROM [Customers] AS [t0]
LEFT OUTER JOIN [Orders] AS [t1] ON [t0].[CustomerID] = [t1].[CustomerID]
GROUP BY [t0].[CustomerID]

Though a little cleaner and look performant, but still not as succint and performant compared to simpler statement: COUNT(O.CustomerID)

Is what I'm trying to do, possible in Linq to SQL?

How about other ORM? notably NHibernate, can it translate the HQL statement to its real SQL?

Community
  • 1
  • 1
Michael Buen
  • 38,643
  • 9
  • 94
  • 118
  • 2
    People have a hard enough time writing SQL; I don't expect an abstraction layer to be better. – OMG Ponies Sep 24 '10 at 18:36
  • I concur, it seems I will only use ORM for persistence layer. I don't find reporting needs (especially those complex ones) could be met in a straightforward manner by ORMs (or at least in Linq to SQL). Though I want to know if other devs has a certain degree of success on using ORM for their reporting needs – Michael Buen Sep 24 '10 at 18:46
  • 1
    Is it possible you're picking nits? What is the execution plan for these queries? Any chance you're worrying about the SQL just for stylistic purposes and not for practical ones? – mattmc3 Feb 05 '11 at 03:31
  • It's practical, subquery are performance-killers. Not for stylistic purposes, if subquery proves performant, I don't have problems with that – Michael Buen Feb 05 '11 at 05:49

1 Answers1

2

I think you generally have to live with what LINQ to SQL generates, but hopefully LINQ to SQL will allow you to ignore the SQL altogether (most of the time) - I find that to be a valuable tradeoff.

Regarding complex reports, I usually drop out of LINQ to SQL and write pure SQL, especially when the query involves lots of database-specific UDF's and the like.

shaunmartin
  • 3,849
  • 2
  • 25
  • 26