2009-01-05 10 views
48

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

je 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 bits qui est non annulable (xx.online) comment puis-je mis à false si elle est nulle?

+3

Vous voulez dire "aa.Online"? "xx" n'est défini nulle part ... –

Répondre

55

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

(aa/xx pourrait être interchangeable (une faute de frappe dans la question), la question originale parle de xx mais seulement définit aa)

-à-dire

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

ou si vous voulez que le défaut d'être false (non null):

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

Mise à jour; en réponse à la downvote, j'ai enquêté plus ... le fait est, 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?

+0

Difficile de garder le représentant plus de 200 par jour!?!?! Oui en effet. J'ai vérifié [System.Data.Linq.SqlClient.SqlMethods] (http://msdn.microsoft.com/en-us/library/system.data.linq.sqlclient.sqlmethods.aspx) et il n'y a aucune méthode pour assurer Le 'ISNULL' de SQL est produit donc je vais utiliser votre code :-) – dumbledad

+0

Que diriez-vous de faire un JOIN avec ISNULL? Est-ce que la même chose va marcher? Est-ce nécessaire? – Matt

+0

Ouais et j'ai essayé cela et assez près ne l'a pas coupé. il a créé une déclaration de cas, donc quand je l'ai couru, il a renvoyé trop de données. Après que j'ai enlevé la déclaration de cas, le sql est revenu très bien ... désolé de devoir le rétrograder – Clarence

0

On dirait que le type est booléen et ne peut donc jamais être nul et devrait être faux par défaut.

+1

Comment pouvez-vous le rendre faux par défaut si c'est à partir d'une jointure? – MartGriff

+0

Ce sera faux par défaut sûrement? C'est un booléen et n'a pas été défini, donc cela devrait être faux. Que vois-tu? –

23

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

J'ai souvent ce problème avec les séquences (par opposition aux valeurs discrètes). Si j'ai une séquence d'ints, et que je veux les SUM, quand la liste est vide, je recevrai l'erreur "InvalidOperationException: La valeur null ne peut pas être assignée à un membre avec le type System.Int32 qui est une valeur non nullable type.".

Je trouve que je peux résoudre ce problème en transformant la séquence en type nullable. SUM et les autres opérateurs d'agrégat ne lancent pas cette erreur si une séquence de types nullable 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 sera de retour 0 si aucune ligne ne correspond à la clause where. (le premier lève une exception lorsqu'aucune ligne ne correspond).