【发布时间】:2011-04-16 22:24:03
【问题描述】:
在 Linq to Sql 中是否可以实现干净的(或者我应该说是高性能的)SQL?
我希望 Linq to Sql 生成以下代码:
SELECT C.CustomerID, COUNT(O.CustomerID) AS N
FROM Customers C
LEFT JOIN Orders O ON O.CustomerID = C.CustomerID
GROUP BY C.CustomerID
我遵循以下代码:LINQ - Left Join, Group By, and Count
这是我的代码版本:
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) };
但它会生成这个...
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]
...我认为这是不可接受的。
那我试试这个……
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 )};
...这是结果查询:
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]
虽然更简洁,看起来更高效,但与更简单的语句相比仍然没有那么简洁和高效:COUNT(O.CustomerID)
在 Linq to SQL 中我正在尝试做的事情是否可行?
其他 ORM 呢?尤其是 NHibernate,它能否将 HQL 语句翻译成真正的 SQL?
【问题讨论】:
-
人们写SQL已经够辛苦了;我不认为抽象层会更好。
-
我同意,看来我只会将 ORM 用于持久层。我没有发现 ORM(或至少在 Linq to SQL 中)可以直接满足报告需求(尤其是那些复杂的需求)。虽然我想知道其他开发人员在使用 ORM 满足他们的报告需求方面是否取得了一定程度的成功
-
你有没有可能在挑毛病?这些查询的执行计划是什么?您是否会担心 SQL 只是出于文体目的而不是出于实际目的?
-
很实用,子查询是性能杀手。不是出于文体目的,如果子查询证明是高性能的,我对此没有问题
标签: sql orm linq-to-sql