[英]What's the difference between these two LINQtoSQL statements?
這兩個語句在邏輯上與我看起來相同,但它們導致生成不同的SQL:
#1
var people = _DB.People.Where(p => p.Status == MyPersonEnum.STUDENT.ToString());
var ids = people.Select(p => p.Id);
var cars = _DB.Cars.Where(c => ids.Contains(c.PersonId));
#2
string s = MyPersonEnum.STUDENT.ToString();
var people = _DB.People.Where(p => p.Status == s);
var ids = people.Select(p => p.Id);
var cars = _DB.Cars.Where(c => ids.Contains(c.PersonId));
示例#1不起作用,但示例#2起作用。
var people
查詢生成的SQL對於兩者都是相同的,但最終查詢中的SQL不同,如下所示:
#1
SELECT [t0].[PersonId], [t0].[etc].....
FROM [Cars] AS [t0]
WHERE EXISTS(
SELECT NULL AS [EMPTY]
FROM [People] AS [t1]
WHERE ([t1].[Id] = [t0].[PersonId]) AND ([t1].[Status] = (CONVERT(NVarChar,@p0)))
)
#2
SELECT [t0].[PersonId], [t0].[etc].....
FROM [Cars] AS [t0]
WHERE EXISTS(
SELECT NULL AS [EMPTY]
FROM [People] AS [t1]
WHERE ([t1].[Id] = [t0].[PersonId]) AND ([t1].[Status] = @p0)
)
為什么會出現這種差異?
到目前為止,我所做的一切只是為了檢查調試器中的可查詢性。 但是,在設置了Jon建議的記錄器之后,似乎執行的真實 sql是不同的。
#1
SELECT [t1].[Id], [t1].etc ... [t0].Id, [t1].etc ...
FROM [Cars] AS [t0], [People] AS [t1]
WHERE ([t1].[Id] = [t0].[PersonId]) AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [People] AS [t2]
WHERE ([t2].[Id] = [t0].[PersonId]) AND ([t2].[Status] = (CONVERT(NVarChar,@p0)))
)) AND ([t1].[Status] = @p1)
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [2]
-- @p1: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [STUDENT]
#2
SELECT [t1].[Id], [t1].etc ... [t0].Id, [t1].etc ...
FROM [Cars] AS [t0], [People] AS [t1]
WHERE ([t1].[Id] = [t0].[PersonId]) AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [People] AS [t2]
WHERE ([t2].[Id] = [t0].[PersonId]) AND ([t2].[Status] = @p0)
)) AND ([t1].[Status] = @p1)
-- @p0: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [STUDENT]
-- @p1: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [STUDENT]
不,他們是不同的。 在第一個版本中,表達式MyPersonEnum.STUDENT.ToString()
位於表達式樹中 - 它是LINQ to SQL必須轉換為SQL的一部分。 我有興趣看看執行查詢時@p0
是什么...
在第二個版本中,您已經評估了表達式,因此LINQ to SQL只會看到對已經是字符串的變量的引用。
我們知道它們的意思相同,但可能是LINQ to SQL沒有足夠的知識來理解它。
出於興趣,他們兩個都有效嗎?
編輯:好的,所以第二個版本的工作原理。 我建議你使用那種形式然后:)在一個理想的世界中,兩者都可以工作 - 但在這種情況下,你似乎需要幫助LINQ to SQL一點。
首先,想想e Enum的雙重性:
enum MyPersonEnum
{
STUDENT, // implicit 1
TEACHER, // implicit 2
DIRECTOR = 10 // explicit 10
}
...
Assert.AreEqual(1, (int)MyPersonEnum.STUDENT);
Assert.AreEqual("STUDENT", MyPersonEnum.STUDENT.ToString());
在第二個示例中,C#已將Enum轉換為字符串,因此不需要轉換,並且假設您的數據庫People.Status列接受“STUDENT”,“TEACHER”,“DIRECTOR”字符串作為邏輯中的有效值。
區別在於,CLR中的枚舉內部表示是整數,第一個示例,@ p參數作為整數傳遞,它是L2S查詢構建器行為,這就是轉換的原因。
如果您的數據庫列是一個int,在我的示例中將值分配給Enum成員{1,2,10},則第一個將起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.