如果表中的字段類型為 char(1) 時,Linq to SQL生成char (System.Char)的屬性,如下圖
表定義 生成的實體2.
如果要查詢LineCode=='A'的記錄,可以這樣定義Linq查詢語句
var test1 = from p in db.ProductLines where p.LineCode =='A' select p;生成的SQL語句是這樣的
SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount] FROM [dbo].[ProductLine] AS [t0] WHERE UNICODE([t0].[LineCode]) = @p0 -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [65] -- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.21022.8注意到Where語句了嗎?是WHERE UNICODE([t0].[LineCode]) = 65,這裡先取LineCode列內容的UNICODE再和'A'的UNICODE比較。我們知道'A'和'a'的UNICODE是不同的。UNICODE('A') =65,UNICODE('a')=97,也就是說,我們在Linq to SQL中這二個查詢的結果是不一樣的。
Linq 語句 var test1 = from p in db.ProductLines where p.LineCode =='a' select p; var test1 = from p in db.ProductLines where p.LineCode =='A' select p; 生成SQL語句 SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount] FROM [dbo].[ProductLine] AS [t0] WHERE UNICODE([t0].[LineCode]) = @p0 -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [97] SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount] FROM [dbo].[ProductLine] AS [t0] WHERE UNICODE([t0].[LineCode]) = @p0 -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [65]明顯,在Linq to sql是查詢char(1)類型字段是區分大小寫的。
這還會導致一個比較嚴重的問題,我們知道在SQL Server中,任何在運算符左邊的操作都會使SQL采用全表掃描。也就是說,Linq的這個查詢,會引起全表掃描,即使[LineCode]列上定義了聚合索引。而如果是where [linecode]='A',則可以使用索引。我們看下這二種情況時的查詢執行計劃對比。
圖中可以看出,Linq to SQL 生成的SQL語句是表掃描,而後者則是索引查找。
3.
對策
在DBML設計器中將LineCode改成string類型。
看一下改了之後的查詢
var test1 = from p in db.ProductLines where p.LineCode == "a" select p; SELECT [t0].[LineCode], [t0].[LineName], [t0].[JPH], [t0].[QueueCount] FROM [dbo].[ProductLine] AS [t0] WHERE [t0].[LineCode] = @p0 -- @p0: Input VarChar (Size = 1; Prec = 0; Scale = 0) [a] -- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.21022.8 Linq sql改為string後,生成的SQL不再用UNICODE函數了,就解決了區分大小寫和引起全表掃描的問題。但又引起一個新的問題,因為數據庫中存儲的數據長度是1,在Insert和Update時就要注意,LineCode不要輸入過長的內容,否則會出錯了。