我正在做一些測試與EF
和Linq to entities
來嘗試和提高我的應用程序性能。Linq到實體順序由sql
我只是注意到一些奇怪的東西(對我來說),我無法解釋,也無法確定是否會產生相當大的開銷。
這裏是我的LINQ:
var result = from n in query
orderby n.PersonId
select new
{
id = n.Id,
appointmentId = n.AppointmentId,
message = n.Message,
wasRead = n.Read,
canDismiss = (n.Appointment.Status != AppointmentStatus.Waiting),
date = n.IssueDateUtc
};
這是生成的sql:
SELECT
[Project1].[Id] AS [Id],
[Project1].[AppointmentId] AS [AppointmentId],
[Project1].[Message] AS [Message],
[Project1].[Read] AS [Read],
[Project1].[C1] AS [C1],
[Project1].[IssueDateUtc] AS [IssueDateUtc]
FROM (SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Read] AS [Read],
[Extent1].[Message] AS [Message],
[Extent1].[IssueDateUtc] AS [IssueDateUtc],
[Extent1].[AppointmentId] AS [AppointmentId],
[Extent1].[PersonId] AS [PersonId],
CASE WHEN (NOT ((1 = [Extent2].[Status]) AND ([Extent2].[Status] IS NOT NULL))) THEN cast(1 as bit) WHEN (1 = [Extent2].[Status]) THEN cast(0 as bit) END AS [C1]
FROM [dbo].[Notification] AS [Extent1]
LEFT OUTER JOIN [dbo].[Appointment] AS [Extent2] ON [Extent1].[AppointmentId] = [Extent2].[Id]
WHERE [Extent1].[PersonId] = @p__linq__0
) AS [Project1]
**ORDER BY [Project1].[PersonId] ASC**
我不明白,需要一種羣體的結果在其他投影(Project1
),而這似乎工作得很好:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Read] AS [Read],
[Extent1].[Message] AS [Message],
[Extent1].[IssueDateUtc] AS [IssueDateUtc],
[Extent1].[AppointmentId] AS [AppointmentId],
[Extent1].[PersonId] AS [PersonId],
CASE WHEN (NOT ((1 = [Extent2].[Status]) AND ([Extent2].[Status] IS NOT NULL))) THEN cast(1 as bit) WHEN (1 = [Extent2].[Status]) THEN cast(0 as bit) END AS [C1]
FROM [dbo].[Notification] AS [Extent1]
LEFT OUTER JOIN [dbo].[Appointment] AS [Extent2] ON [Extent1].[AppointmentId] = [Extent2].[Id]
WHERE [Extent1].[PersonId] = @p__linq__0
**ORDER BY [Extent1].[PersonId] ASC**
我發現了相當數量的由ef和linq生成的有問題的sql,我開始懷疑我是不是更好,只是寫了原始的sqls。
問題是:生成的sql額外的代碼是需要擔心的一些問題?爲什麼這個投影是必要的?
編輯添加一個新的LINQ
正如在評論中提到的,也許是冗長被後續查詢正在運行造成的。我改寫了LINQ只使用一個查詢對象,結果還是一樣:
dbSet.Where(n => n.PersonId == id).Select(n => new
{
Id = n.Id,
AppointmentId = n.AppointmentId,
Message = n.Message,
Read = n.Read,
CanBeDismissed = (n.Appointment.Status != AppointmentStatus.Waiting),
IssueDate = n.IssueDateUtc
}).OrderBy(n => n.Id).ToList();
執行計劃(兩者相同sqls
)
編輯2
剛從簡單計數中得到這個查詢。
dbSet.Count(x => x.Id == 1 && x.Read == false);
SELECT
[GroupBy1].[A1] AS [C1]
FROM (SELECT
COUNT(1) AS [A1]
FROM [dbo].[Notification] AS [Extent1]
WHERE ([Extent1].[PersonId] = 19) AND (0 = [Extent1].[Read])
) AS [GroupBy1]
預計:
SELECT
COUNT(1) AS [A1]
FROM [dbo].[Notification] AS [Extent1]
WHERE ([Extent1].[PersonId] = 19) AND (0 = [Extent1].[Read])
我不明白,所有這種包裝是從,爲什麼來了。
我想'query'是另一個LINQ到SQL查詢,那就是你所看到的嵌套在投影內部。這正是你在用LINQ做什麼。如果你想擺脫它,只需將'OrderBy'和'Select'添加到'query'中。但是如果使用後續的LINQ查詢使得代碼更清晰,請不要擔心......如果有的話,投影的開銷很小。如果有疑問,請比較執行計劃。但是,如果你看到性能問題,肯定不會是由該投影造成的。 –
關於您對LINQ-to-SQL生成查詢的擔心......我發現Linq-to-SQL生成優秀(但通常是冗長)的SQL查詢,甚至在複雜場景中更多。我會說這比大多數程序員能夠實現的要好。但是,它當然也需要寫得很好的LINQ查詢。所以你最好仔細檢查一下生成的SQL ......但總的來說,不用擔心,LINQ通常對於何時使用連接,交叉應用或其他表現最好的東西做出了很好的選擇,但我實際上經常從看在LINQ生成的SQL;) –
我總是在學習新東西。我只是擔心,因爲我沒有對sgdb進行過多的研究,而且我的產品也在不斷增長,現在我花時間分析db訪問,看到相當可怕的代碼,並且只是重寫了表達式,我能夠在大約60% 。無論如何,我只用一個查詢重寫了linq,結果是一樣的。我會將其添加到問題中,請查看。我認爲額外的代碼是由於使用匿名類型而生成的。 – victor