Обнуляемый Guid в Linq to Sql дает неожиданный результат - PullRequest
3 голосов
/ 30 марта 2012

У меня есть простая таблица SQL, которая определяет набор иерархических категорий и подкатегорий - обратите внимание, что ParentCategoryId может быть нулевым для категорий «верхнего уровня» ...

CREATE TABLE [dbo].[Category](
    [CategoryId] [uniqueidentifier] NOT NULL,
    [ParentCategoryId] [uniqueidentifier] NULL,
    [Name] [nvarchar](50) NOT NULL
)

Если я тогда создаюВыражение Linq для поиска определенной категории по Name и ParentCategoryId, я нахожу, что не могу получить правильный результат, если я установил Guid?переменная в нуль:

Guid? parentCategoryId = null;

var category = dc.Categories
    .Where(c => (
        (c.Name == "Fred") &&
        (c.ParentCategoryId == parentCategoryId)
));

Это не дает тот же результат, что и:

var category = dc.Categories
    .Where(c => (
        (c.Name == "Fred") &&
        (c.ParentCategoryId == null)
));

Из того, что я могу найти в Интернете, у других была эта проблема, но у меня нетЯ не смог найти чистый обходной путь для решения проблемы.

Любые идеи будут высоко оценены.Спасибо.

Дополнительная информация Вот сгенерированные LINQ операторы SQL для первого Guid?нулевой параметр, а затем для простого нулевого параметра:

-- With Guid? null parameter : return an empty record set
DECLARE @p0 NVarChar(1000) SET @p0 = 'Fred'
DECLARE @p1 UniqueIdentifier SET @p1 = null
SELECT [t0].[CategoryId], [t0].[ParentCategoryId], [t0].[Name], [t0].[Timestamp]
FROM [dbo].[cad_ScoCategory] AS [t0]
WHERE ([t0].[Name] = @p0) AND ([t0].[ParentCategoryId] = @p1)


-- With null parameter - returns a single (correct) record
DECLARE @p0 NVarChar(1000) SET @p0 = 'Fred'
SELECT [t0].[CategoryId], [t0].[ParentCategoryId], [t0].[Name], [t0].[Timestamp]
FROM [dbo].[cad_ScoCategory] AS [t0]
WHERE ([t0].[Name] = @p0) AND ([t0].[ParentCategoryId] IS NULL)

Как видите, первый вариант сравнивает ParentCategoryId с нулевым параметром, где в качестве второго метода проверяется ParentCategoryId IS NULL - что правильно

1 Ответ

8 голосов
/ 30 марта 2012

Нет, к сожалению, это довольно распространенная проблема. Обходной путь должен явно сравнить с нулем:

.Where(c => c.Name == Fred &&
           ((c.ParentCategoryId == parentCategoryId) ||
            (c.ParentCategoryId == null && parentCategoryId == null)))

Либо выполните проверку за пределами запроса (чтобы изменить используемый фильтр):

var category = dc.Categories.Where(c => c.Name == "Fred");
category = parentCategoryId == null 
    ? category.Where(c => c.ParentCategoryId == null)
    : category.Where(c => c.ParentCategoryId == categoryId);
...