Как я могу вернуться, если из запроса Entity Framework существует необязательное свойство навигации? - PullRequest
3 голосов
/ 07 октября 2010

Я пытаюсь вернуть логическое значение, используя следующий запрос:

var q = from inmate in context.Inmates
        select new
        {
            inmate.Id,
            IsCrazy = inmate.Certified != null
        };

IsCrazy должно быть true, только если необязательное свойство навигации Certified не равно нулю.Тем не менее, IsCrazy всегда возвращается как true, независимо от того, существует ли связь между Inmate > Certified.

, используя приведенный выше код и следующие данные:

Inmate { 1 } --> { Certified }
Inmate { 2 } --> NULL
Inmate { 3 } --> { Certified }

Я ожидалследующие результаты:

1, true
2, false
3, true

Однако все результаты возвращаются.Что я делаю не так?

Затем я попытался вернуть необязательное свойство навигации вместо этого, но, похоже, это делает внутреннее соединение, и только возвращает сумасшедших заключенных:

Inmate { 1 } --> { Certified }
Inmate { 3 } --> { Certified }
// Inmate 2 is missing

РЕДАКТИРОВАТЬ: Забыл упомянуть, я сначала использую код EF 4.0.

РЕДАКТИРОВАТЬ 2:

Это вывод SQL

SELECT 
[Extent1].[Id] AS [Id], 
CASE WHEN (cast(1 as bit) <> cast(0 as bit)) 
THEN cast(1 as bit) WHEN (1 = 0) THEN cast(0 as bit) END AS [C1]
FROM [dbo].[Inmate] AS [Extent1]

Выглядит совершенно неправильно для меня;нет никакого упоминания о Certified вообще.

РЕДАКТИРОВАТЬ 3:

Я попробовал следующий код в LINQPad (отбрасывая вещь заключенного, это мой настоящий код):

from i in Ingredients
join m in Meats 
    on new { i.IngId, i.VersionId } equals new { m.IngId, m.VersionId } into temp
from t in temp.DefaultIfEmpty()
select new
{
    IngId = i.IngId,
    IsMeat = t.MeatTypeId == null ? false : true
};

Это вернет все 3000 результатов с правильными значениями true / false.Тот же код в Entity Framework будет возвращать только те результаты, для которых выполнено отношение один к одному.

Это SQL, сгенерированный LINQPad:

-- Region Parameters
DECLARE @p0 Int SET @p0 = 0
DECLARE @p1 Int SET @p1 = 1
-- EndRegion
SELECT [t0].[IngId], 
    (CASE 
        WHEN ([t1].[MeatTypeId]) IS NULL THEN @p0
        ELSE @p1
     END) AS [IsMeat]
FROM [Ingredient] AS [t0]
LEFT OUTER JOIN [MeatIngredient] AS [t1] ON ([t0].[IngId] = [t1].[IngId]) 
    AND ([t0].[VersionId] = [t1].[VersionId])

Это сгенерированный SQLпо EF:

SELECT 
[Extent1].[IngId] AS [IngId], 
cast(1 as bit) AS [C1]
FROM  [dbo].[Ingredient] AS [Extent1]
INNER JOIN [dbo].[MeatIngredient] AS [Extent2] 
    ON ([Extent1].[VersionId] = [Extent2].[VersionId]) 
        AND ([Extent1].[IngId] = [Extent2].[IngId])

Ответы [ 3 ]

1 голос
/ 08 октября 2010

Ну, мне удалось заставить его работать, как и ожидалось, думая задом наперед.Т.е. проверка на обнуляемое мясо содержит ингредиент (или, если все еще в первоначальном примере, проверьте, есть ли в сертификате действительный заключенный):

var q = from i in context.Ingredients
        let m = i.Meat // AKA Certificate
        select new 
        {
            IngId = i.IngId,
            IsMeat = m.Ingredient != null 
        };

SQL-код для такого простого запроса неприятенЭто примерно в 4 раза больше, чем было бы, если бы я сам написал хранимую процедуру.Однако он работает за 57 мс, так что беспокоиться не о чем.

0 голосов
/ 07 октября 2010

Продолжайте и попробуйте выполнить внешнее левое соединение:

var q = from inmate in context.Inmates
join c in Certified on inmate.cId equals c.Id into temp //replace with whatever you will join on
from temp in temp.DefaultIfEmpty()
select new { inmate.Id, IsCrazy = c.IsCertified != null }; //replace to what it is you want to check

Это будет что-то подобное.Для более конкретного примера это может помочь узнать немного больше о структуре базы данных здесь.Надеюсь, это поможет.

0 голосов
/ 07 октября 2010

Не знаю, поможет ли это.но попробуйте

IsCrazy =! inmate.Certific.Equals (System.DBNull.Value)

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