我有这个疑问:
select '[' + p.Firstname + ']' from Person p
where p.Firstname = 'Johanne'
在表中,我有多个人有这个名字,有些人的值上有尾随空格(值插入错误,将被纠正)。
为什么这个查询会给我带来这个结果(我插入了括号来可视化空格):
[Johanne]
[Johanne ]
[Johanne ]
[Johanne]
这是一个配置问题吗?真正的查询来自实体框架 6,但本示例也这样做。我该如何预防?
谢谢!
编辑:我可以使用 EF6 和
System.Data.Entity.SqlServer.SqlFunctions.DataLength
方法使其工作,如下所示:
ctx.Person.FirstOrDefault(p => p.FirstName == "Johanne" && SqlFunctions.DataLength(p.FirstName) == "Johanne".Length);
SQL Server 遵循有关如何将字符串与空格进行比较的 ANSI/ISO SQL-92 规范(第 8.2 节,一般规则 #3)。 ANSI 标准要求对比较中使用的字符串进行填充,以便在比较之前它们的长度匹配。填充直接影响 WHERE 和 HAVING 子句谓词以及其他 Transact-SQL 字符串比较的语义。例如,对于大多数比较操作,Transact-SQL 认为字符串 'abc' 和 'abc ' 是等效的。
此规则的唯一例外是 LIKE 谓词。当 LIKE 谓词表达式右侧的值带有尾随空格时,SQL Server 在比较发生之前不会将两个值填充到相同的长度。因为根据定义,LIKE 谓词的目的是促进模式搜索而不是简单的字符串相等性测试,因此这并不违反前面提到的 ANSI SQL-92 规范的部分。
我不确定在 EF 中,但在 TSQL 中我使用 DataLength
DataLength 将返回包括尾随空格的长度
Len 将返回不包括尾随空格的长度
and DataLength(p.Firstname) = Len('Johanne')
您可以在 Sql 中创建一个新视图并将该视图映射回 EF 对象。视图可以包含字段的长度,在使用 DataLength 的选择中,您知道要匹配,然后在使用 EF 时可以在 where 子句中对其进行过滤。 或者,您可以创建一个 Sql 存储过程,使用不带通配符的 LIKE 进行比较(这会产生所需的结果),并将其映射回您的代码,并在 EF 的Where 语句中调用它。
使用视图
Create View MyCustomView
AS
SELECT [column1,column2,etc], DATALENGTH(FirstName) AS FirstNameLength
FROM Person
GO
那么你的 EF 将是:
Persons.Where(p => p.FirstNameLength == "Johanne".Length && p.FirstName == "Johanne");
使用存储过程
CREATE PROCEDURE [dbo].[GetPersons]
firstName int = null
AS
BEGIN
SET NOCOUNT ON;
select [your fields here]
from persons
where FirstName like @firstName
END
在 C# 中确保您的映射正确,然后
this.Database.SqlQuery<Person>("GetPersons","Johanne");
EF6还支持在执行之前直接编辑DbContext中的sql。您可以开发一些自定义代码,在特定情况下用 like 替换 =,但在执行此操作之前先尝试上述内容可能更容易。