web-dev-qa-db-fra.com

Équivalent de SQL ISNULL dans LINQ?

En SQL, vous pouvez exécuter un ISNULL (null, '') comment feriez-vous cela dans une requête linq?

J'ai une jointure dans cette requête:

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
        };

mais j'ai une colonne qui a un type de bit qui n'est pas nullable (xx.online) comment puis-je définir cela sur false s'il est nul?

49
MartGriff

Puisque aa est l'ensemble/objet qui peut être nul, pouvez-vous vérifier aa == null?

(aa/xx peut être interchangeable (une faute de frappe dans la question); la question d'origine parle de xx mais définit uniquement aa)

c'est à dire.

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

ou si vous voulez que la valeur par défaut soit false (pas null):

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

Mise à jour; en réponse au vote négatif, j'ai enquêté davantage ... le fait est que c'est la bonne approche! Voici un exemple sur 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);
            }
        }

Et voici le TSQL - à peu près ce que nous voulons (ce n'est pas ISNULL, mais il est assez proche):

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

QED?

58
Marc Gravell

Vous pouvez utiliser le ?? opérateur pour définir la valeur par défaut, mais vous devez d'abord définir la propriété Nullable sur true dans votre fichier dbml dans le champ requis (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
        };
24
bruno conde

J'ai souvent ce problème avec les séquences (par opposition aux valeurs discrètes). Si j'ai une séquence d'entiers et que je veux les résumer, lorsque la liste est vide, je reçois l'erreur "InvalidOperationException: la valeur nulle ne peut pas être affectée à un membre de type System.Int32 qui est une valeur non nulle. type.".

Je trouve que je peux résoudre ce problème en convertissant la séquence en un type nullable. SUM et les autres opérateurs d'agrégation ne génèrent pas cette erreur si une séquence de types nullables est vide.

Ainsi, par exemple quelque chose comme ça

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

devient

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

Le second retourne 0 lorsqu'aucune ligne ne correspond à la clause where. (le premier lève une exception lorsqu'aucune ligne ne correspond).

1
Slaggg

Il semble que le type soit booléen et ne puisse donc jamais être nul et devrait être faux par défaut.

0
Ray Booysen