我花費了大量時間試圖弄清楚爲什麼Linq2SQL正在更改我的SQL查詢。這是很難解釋,我找不到任何理由爲什麼發生這種情況。最低限度的是看起來,添加多個包含IQueryable似乎覆蓋了每個以前的IQueryable表達式。讓我試着解釋一下:添加多個包含IQueryable到基礎IQueryable每更改一次前面的IQueryable
假設你有一個Linq2SQL查詢,它提供了查詢的基本框架。 (這是你的所有查詢的基礎)
我動態地添加了部分where查詢(在下面的示例中顯示爲「partQuery」)。從where查詢生成的Expression是正確的,當我將它添加到finalQuery時 - 它仍然是正確的。當我向最終查詢中添加另一個partQuery時,問題就出現了,它似乎覆蓋了最終查詢中的第一個查詢,但向其中添加了第二個查詢。 (或者,如下所示,加入第三個查詢時,將覆蓋第一2個查詢)
下面是一些源例如:
foreach (var partQuery in whereStatements)
{
finalQuery = finalQuery.Where(
dataEvent => partQuery.Contains(dataEvent.DataEventID)
);
}
的partQuery是類型的IQueryable finalQuery是查詢,最終將在SQL服務器
// the list of the wheres that are sent
var whereStatements = new List<IQueryable<long>>();
var query1 = DataEvent.GetQueryBase(context);
query1 = query1.Where(
dataEvent =>
dataEvent.DataEventKeyID == (short)DataEventTypesEnum.TotalDollarAmount && dataEvent.ValueDouble < -50);
whereStatements.Add(query1.Select(x => x.DataEventID));
var query2 = DataEvent.GetQueryBase(context);
query2 = query2.Where(
dataEvent =>
dataEvent.DataEventKeyID == (short)DataEventTypesEnum.ObjectNumber && dataEvent.ValueDouble == 6);
whereStatements.Add(query2.Select(x => x.DataEventID));
執行的第一其中查詢(QUERY1)具有原來像這樣的表達式:
{SELECT [t0].[DataEventID]
FROM [dbo].[DataEvents] AS [t0]
INNER JOIN [dbo].[DataEventAttributes] AS [t1] ON [t0].[DataEventID] = [t1].[DataEventID]
WHERE ([t1].[DataEventKeyID] = @p0) AND ([t1].[ValueDouble] < @p1)
}
注意,其中線具有ValueDouble「<」 @ P1 - 小於
,然後當加入到最終的查詢,它看起來像這樣:
{SELECT [t0].[DataEventID], [t0].[DataOwnerID], [t0].[DataTimeStamp]
FROM [dbo].[DataEvents] AS [t0]
WHERE (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DataEvents] AS [t1]
INNER JOIN [dbo].[DataEventAttributes] AS [t2] ON [t1].[DataEventID] = [t2].[DataEventID]
WHERE ([t1].[DataEventID] = [t0].[DataEventID]) AND ([t2].[DataEventKeyID] = @p0) AND ([t2].[ValueDouble] < @p1)
)) AND ([t0].[DataOwnerID] = @p2)
}
在這一點上,該查詢仍然正確。請注意ValueDouble如何仍具有「<」符號。當我向查詢添加2個或更多時發生問題。這是第二個查詢在這個例子中,表達式:
{SELECT [t0].[DataEventID]
FROM [dbo].[DataEvents] AS [t0]
INNER JOIN [dbo].[DataEventAttributes] AS [t1] ON [t0].[DataEventID] = [t1].[DataEventID]
WHERE ([t1].[DataEventKeyID] = @p0) AND ([t1].[ValueDouble] = @p1)
}
,當添加到最終的查詢..你會發現,第一次查詢不再是正確的......(而且更多的驚喜之後)
{SELECT [t0].[DataEventID], [t0].[DataOwnerID], [t0].[DataTimeStamp]
FROM [dbo].[DataEvents] AS [t0]
WHERE (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DataEvents] AS [t1]
INNER JOIN [dbo].[DataEventAttributes] AS [t2] ON [t1].[DataEventID] = [t2].[DataEventID]
WHERE ([t1].[DataEventID] = [t0].[DataEventID]) AND ([t2].[DataEventKeyID] = @p0) AND ([t2].[ValueDouble] = @p1)
)) AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DataEvents] AS [t3]
INNER JOIN [dbo].[DataEventAttributes] AS [t4] ON [t3].[DataEventID] = [t4].[DataEventID]
WHERE ([t3].[DataEventID] = [t0].[DataEventID]) AND ([t4].[DataEventKeyID] = @p2) AND ([t4].[ValueDouble] = @p3)
)) AND ([t0].[DataOwnerID] = @p4)
}
和獎金吧...在此通過SQL事件探查器後看,似乎它完全放棄了第一查詢,這兩個存在於最終的SQL條款實際上是相同的查詢(QUERY2 )。沒有任何參數實際傳遞給SQl服務器進行第一個查詢。
因此,在我對此的研究中,它似乎將SQl的查詢添加到SQl中,但它將所有已存在的where子句替換爲已添加的最後一個。要加倍確認這個..與上面完全相同的代碼,但我添加了第三個查詢....並查看它是如何改變的。
var query3 = DataEvent.GetQueryBase(context);
query3 = query3.Where(
dataEvent =>
dataEvent.DataEventKeyID != (short)DataEventTypesEnum.Quantity && dataEvent.ValueDouble != 5);
whereStatements.Add(query3.Select(x => x.DataEventID));
我在一些扔「!=」到查詢的最後一部分
{SELECT [t0].[DataEventID], [t0].[DataOwnerID], [t0].[DataTimeStamp]
FROM [dbo].[DataEvents] AS [t0]
WHERE (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DataEvents] AS [t1]
INNER JOIN [dbo].[DataEventAttributes] AS [t2] ON [t1].[DataEventID] = [t2].[DataEventID]
WHERE ([t1].[DataEventID] = [t0].[DataEventID]) AND ([t2].[DataEventKeyID] <> @p0) AND ([t2].[ValueDouble] <> @p1)
)) AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DataEvents] AS [t3]
INNER JOIN [dbo].[DataEventAttributes] AS [t4] ON [t3].[DataEventID] = [t4].[DataEventID]
WHERE ([t3].[DataEventID] = [t0].[DataEventID]) AND ([t4].[DataEventKeyID] <> @p2) AND ([t4].[ValueDouble] <> @p3)
)) AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[DataEvents] AS [t5]
INNER JOIN [dbo].[DataEventAttributes] AS [t6] ON [t5].[DataEventID] = [t6].[DataEventID]
WHERE ([t5].[DataEventID] = [t0].[DataEventID]) AND ([t6].[DataEventKeyID] <> @p4) AND ([t6].[ValueDouble] <> @p5)
)) AND ([t0].[DataOwnerID] = @p6)
}
通知所有三個內部查詢,現在怎麼都是「<>」,其中上面的查詢是不是。
我完全擺脫了我的搖桿嗎?我是否錯過了這麼簡單的事情,當你告訴我我想要拔掉我的指甲?我實際上希望你告訴我,而不是告訴我,它看起來像MS框架中的錯誤(嗯,我們知道有時會發生)。
任何幫助,非常感謝。也許我應該以不同的方式將動態查詢部分發送到基本查詢。我對想法持開放態度。
該死的,我再也不會忽視我的警告了。它在VS中被強調,但我忽略了它。我認爲範圍本來是一樣的。 非常感謝..第二組眼睛似乎已經解決了我的問題:) – TravisWhidden 2009-09-30 16:49:59