Почему я получаю неправильный результат при сравнении строк UTF16 в выделении linq-to-sql? - PullRequest
2 голосов
/ 10 сентября 2011

Я использую C # и .Net 4.0 с MS SQL 2008.

Я запускаю интеграционный тест, чтобы убедиться, что данные правильно хранятся и извлекаются. Это терпит неудачу чаще, чем нет. Когда я смотрю в это, я вижу, что я получаю неправильное значение назад от вызова linq-to-sql. Я профилировал оператор linq-to-sql и обнаружил, что в Server Management Studio профилированный SQL возвращает неправильное значение, в то время как запрос, набранный вручную с теми же параметрами, работает правильно.

Запрос linq-to-sql и результат:

exec sp_executesql N'SELECT TOP (1) [t0].[ID], [t0].[UserName], [t0].TCID
FROM [dbo].[Users] AS [t0]
WHERE ([t0].[TCID] = @p0) AND ([t0].[UserName] = @p1)',N'@p0 int,@p1
nvarchar(4000)',@p0=8,@p1=N'ҭРӱґѻ'

Результаты в

ID        UserName    TCID
2535      ҭРґѻӱ       8

Как видите, UserName не соответствует тому, что было в проверке равенства.

Если я сделаю это, я получу ожидаемый результат:

SELECT TOP 1000 [ID]
    ,[UserName]
    ,[TCID]
FROM [dbo].[Users]
where TCID=8 and username = 'ҭРӱґѻ'

Я вернусь:

ID        UserName    TCID

Что правильно.

UserName - это nvarchar (50), ID и TCID - это int.

Есть идеи, почему первый запрос дает неправильный результат?

Ответы [ 2 ]

2 голосов
/ 10 сентября 2011

Вы не получите результаты по второму запросу, потому что вы забыли добавить префикс к параметру N. Бьюсь об заклад, вы получите результат, как с динамическим SQL, если вы используете:

SELECT TOP 1000 [ID]
    ,[UserName]
    ,[TCID]
FROM [dbo].[Users]
where TCID=8 and username = N'ҭРӱґѻ'; -- note the N prefix here

Теперь я не говорю, что вы должны получить результат, но это должно привести к тому, что поведение между вашими двумя методами тестирования будет согласованным. Что такое сопоставление столбца? Вы можете исправить это, указав двоичное сопоставление. Например, это должно привести к правильному поведению:

SELECT COUNT(*) 
  FROM [dbo].[Users]
  WHERE [UserName] = N'ҭРӱґѻ' COLLATE Latin1_General_BIN;

-- 0

SELECT COUNT(*) 
  FROM [dbo].[Users]
  WHERE [UserName] = N'ҭРґѻӱ' COLLATE Latin1_General_BIN;

-- 1
1 голос
/ 21 сентября 2011

В используемой вами сортировке (возможно, для сортировки, специфичной для SQL Server), некоторые кодовые точки Unicode не определены. Таким образом, SQL Server обрабатывает их, как если бы они были пустой строкой:

ВЫБЕРИТЕ ДЕЛО, КОГДА N'N 'COLLATE SQL_Latin1_General_CP1_CI_AS = N' 'THEN' YES 'ДАЛЕЕ' NO 'END

Если мы используем более новую сортировку Windows, такую ​​как Cyrillic_General_100_CI_AS, мы видим, что эти строки не совпадают:

ВЫБЕРИТЕ ДЕЛО, КОГДА N'N 'COLLATE Cyrillic_General_100_CI_AS = N' 'THEN' YES 'ELSE' NO 'END

Вот сообщение в блоге на MSDN, которое должно объяснить больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...