Эквивалент SQL ISNULL в LINQ?

В SQL вы можете запустить ISNULL (null, ''), как бы вы сделали это в запросе linq?

У меня есть соединение в этом запросе:

var hht = from x in db.HandheldAssets
        join a in db.HandheldDevInfos on x.AssetID equals a.DevName into DevInfo
        from aa in DevInfo.DefaultIfEmpty()
        select new
        {
        AssetID = x.AssetID,
        Status = xx.Online
        };

но у меня есть столбец с битовым типом, который не может принимать значение NULL (xx.online), как я могу установить для него значение false, если он равен нулю?


person MartGriff    schedule 05.01.2009    source источник
comment
Вы имеете в виду aa.Online ? xx нигде не определен...   -  person Marc Gravell    schedule 05.01.2009


Ответы (4)


Поскольку aa — это набор/объект, который может быть нулевым, можете ли вы проверить aa == null?

(aa / xx могут быть взаимозаменяемыми (опечатка в вопросе); исходный вопрос говорит о xx, но определяет только aa)

i.e.

select new {
    AssetID = x.AssetID,
    Status = aa == null ? (bool?)null : aa.Online; // a Nullable<bool>
}

или если вы хотите, чтобы по умолчанию было false (не null):

select new {
    AssetID = x.AssetID,
    Status = aa == null ? false : aa.Online;
}

Обновлять; в ответ на отрицательное мнение я исследовал больше ... дело в том, что это правильный подход! Вот пример на Northwind:

        using(var ctx = new DataClasses1DataContext())
        {
            ctx.Log = Console.Out;
            var qry = from boss in ctx.Employees
                      join grunt in ctx.Employees
                          on boss.EmployeeID equals grunt.ReportsTo into tree
                      from tmp in tree.DefaultIfEmpty()
                      select new
                             {
                                 ID = boss.EmployeeID,
                                 Name = tmp == null ? "" : tmp.FirstName
                        };
            foreach(var row in qry)
            {
                Console.WriteLine("{0}: {1}", row.ID, row.Name);
            }
        }

А вот TSQL — почти то, что нам нужно (это не ISNULL, но достаточно близко):

SELECT [t0].[EmployeeID] AS [ID],
    (CASE
        WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(10),@p0)
        ELSE [t2].[FirstName]
     END) AS [Name]
FROM [dbo].[Employees] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[FirstName], [t1].[ReportsTo]
    FROM [dbo].[Employees] AS [t1]
    ) AS [t2] ON ([t0].[EmployeeID]) = [t2].[ReportsTo]
-- @p0: Input NVarChar (Size = 0; Prec = 0; Scale = 0) []
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1

КЭД?

person Marc Gravell    schedule 05.01.2009
comment
Трудно поддерживать репутацию более 200 в день!?!?! Да правильно. Я проверил System.Data.Linq.SqlClient. SqlMethods, и там нет метода, обеспечивающего создание SQL ISNULL, поэтому я буду использовать ваш код :-) - person dumbledad; 04.07.2012
comment
Как насчет выполнения JOIN с ISNULL? То же самое будет работать? это необходимо? - person Matt; 23.08.2013
comment
Да, и я попробовал это, и достаточно близко, не разрезал. он создал оператор case, поэтому, когда я его запустил, он вернул слишком много данных. После того, как я удалил оператор case, sql вернулся в порядке... извините, нужно понизить это - person Clarence; 11.05.2017
comment
Как сказал @dumbledad, нет метода, который бы гарантировал SQL ISNULL. Но поскольку подход CASE имеет тот же результат и производительность, что и ISNULL(sqlservercentral.com/Forums /Topic1656650-3412-1.aspx), это пока лучший ответ. - person Dan Mihai Patrascu; 13.10.2018

Вы можете использовать оператор ?? для установки значения по умолчанию, но сначала вы должны установить для свойства Nullable значение true в файле dbml в обязательном поле (xx.Online)

var hht = from x in db.HandheldAssets
        join a in db.HandheldDevInfos on x.AssetID equals a.DevName into DevInfo
        from aa in DevInfo.DefaultIfEmpty()
        select new
        {
        AssetID = x.AssetID,
        Status = xx.Online ?? false
        };
person bruno conde    schedule 05.01.2009
comment
Вам не нужно изменять файл dbml. Вы можете просто привести xx.Online к обнуляемому целому числу. Status = ((int?)xx.Online ?? false) - person xr280xr; 19.05.2021

У меня часто возникает эта проблема с последовательностями (в отличие от дискретных значений). Если у меня есть последовательность целых чисел, и я хочу их СУММИТЬ, когда список пуст, я получу сообщение об ошибке «InvalidOperationException: нулевое значение не может быть присвоено члену с типом System.Int32, который не может быть нулевым значением. тип.".

Я обнаружил, что могу решить эту проблему, приведя последовательность к типу, допускающему значение NULL. SUM и другие агрегатные операторы не выдают эту ошибку, если последовательность типов, допускающих значение NULL, пуста.

Так, например, что-то вроде этого

MySum = MyTable.Where(x => x.SomeCondtion).Sum(x => x.AnIntegerValue);

становится

MySum = MyTable.Where(x => x.SomeCondtion).Sum(x => (int?) x.AnIntegerValue);

Второй вернет 0, если ни одна строка не соответствует предложению where. (первый выдает исключение, когда строки не совпадают).

person Slaggg    schedule 28.08.2010

Похоже, что тип является логическим и, следовательно, никогда не может быть нулевым и по умолчанию должен быть ложным.

person Ray Booysen    schedule 05.01.2009
comment
Как вы можете сделать его ложным по умолчанию, если это из соединения? - person MartGriff; 05.01.2009
comment
Он точно будет ложным по умолчанию? Это логическое значение, которое не было установлено, поэтому оно должно быть ложным. Что вы видите? - person Ray Booysen; 05.01.2009