这两个LINQtoSQL语句之间有什么区别?

Kir*_*ein 5 c# iqueryable linq-to-sql generated-sql

这两个语句在逻辑上与我看起来相同,但它们导致生成不同的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));
Run Code Online (Sandbox Code Playgroud)

示例#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)
    )
Run Code Online (Sandbox Code Playgroud)

为什么会出现这种差异?

编辑:

到目前为止,我所做的一切只是为了检查调试器中的可查询性.但是,在设置了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]
Run Code Online (Sandbox Code Playgroud)

Geo*_*voy 1

首先,考虑 e Enum 的双重性:

enum MyPersonEnum
{
  STUDENT, // implicit 1
  TEACHER, // implicit 2
  DIRECTOR = 10 // explicit 10
}
Run Code Online (Sandbox Code Playgroud)

...

Assert.AreEqual(1, (int)MyPersonEnum.STUDENT);
Assert.AreEqual("STUDENT", MyPersonEnum.STUDENT.ToString());
Run Code Online (Sandbox Code Playgroud)

在第二个示例中,C# 已将 Enum 转换为字符串,因此不需要转换,并且假设数据库 People.Status 列接受“STUDENT”、“TEACHER”、“DIRECTOR”字符串作为逻辑中的有效值。

不同之处在于,CLR 中的枚举内部表示是整数,而第一个示例,@p 参数作为整数传递,这是 L2S 查询构建器的行为,这就是转换的原因。

如果您的数据库列是一个 int,并且在我的示例中采用分配给 Enum 成员 {1,2,10} 的值,则第一个可以工作。