2011-09-20 4 views
0

Je suis nouveau sur linq et j'apprécierais votre aide pour que cette requête de jointure gauche fonctionne.Left join with LINQ Erreur

J'ai "Liste d'heures" (une liste d'heures 0-23) que je voudrais joindre à gauche avec "var hourlyData" (une requête linq traitée contenant des données agrégées). Ma tentative à la jointure gauche est "var reportData".

DataSet ds = GetDataSet(sSql); 
var stats = ds.Tables[0].AsEnumerable(); 

var hourlyData = from stat in stats 
       group stat by stat.Field<int>("Hour") into g 
       select new 
       { 
        Hour = g.Key, 
        Value = g.Key.ToString(), 
        D1 = g.Sum(stat => stat.Field<int>("D1")), 
        D2 = g.Sum(stat => stat.Field<int>("D2")), 
        D3 = g.Sum(stat => stat.Field<decimal>("D3")) 
       }; 


List<int> hours = new List<int>(); 
for (int i = 0; i < 24; i++) 
{ 
    hours.Add(i); 
} 


var reportData = from hour in hours.AsEnumerable() 
       join stat in hourlyData.AsEnumerable() 
        on hour equals stat.Hour 
       into sts2 
       from stat2 in sts2.DefaultIfEmpty() 
       select new 
       { 
        Hour = hour, 
        Value = hour, 
        D1 = stat2.D1 != null ? stat2.D1 : 0, 
        D2 = stat2.D2 != null ? stat2.D2 : 0, 
        D3 = stat2.D3 != null ? stat2.D3 : 0 
       }; 

Le code produit ci-dessus cette erreur:

Détails de l'exception: System.NullReferenceException: référence d'objet non définie à une instance d'un objet.

Erreur Source:

Line 135:       into sts2 
Line 136:       from stat2 in sts2.DefaultIfEmpty() 
Line 137:       select new 
Line 138:       { 
Line 139:        Hour = hour, 
... 

Merci!

+0

Je reçois toujours une erreur. Peut-être que cela offre plus de perspicacité: [NullReferenceException: Référence de l'objet n'est pas définie sur une instance d'un objet.] _Ch. b__b (<> f__AnonymeType1'2 <> h__TransparentIdentifier0, <> f__AnonymousType0'5 stat2) dans System.Linq. d__31'3.MoveNext() +303 System.Collections.Generic.List'1..ctor (Collection IEnumerable'1) +327 System.Linq.Enumerable.ToList (source IEnumerable'1) +58 – mike

+0

Le code actuel lève une exception dans un appel ToList(). Y a-t-il un code après ça? De plus, vous pouvez supprimer tous les appels de 'AsEnumerable()', sauf sur le datatable pour la lisibilité et votre configuration des heures pourrait simplement être 'var heures = Enumerable.Range (0,24)' –

+0

Merci pour votre aide et le raccourci .range ! La réponse simple changeait "D1 = stat2.D1! = Null? Stat2.D1: 0, ..." en "D1 = stat2! = Null? Stat2.D1: 0,". – mike

Répondre

0

Il te donne une NRE parce sts2.DefaultIfEmpty() retourne null. Dans ces cas, vous devrez faire en sorte que vos affectations D1, D2 et D3 dans votre instruction select aient des valeurs par défaut saines si null:

D1 = stat2 != null ? stat2.D1 : 0, 
D2 = stat2 != null ? stat2.D2 : 0, 
D3 = stat2 != null ? stat2.D3 : 0, 
+0

J'ai remarqué que ci-dessus vous avez 'var hourlyData' mais dans votre clause de jointure vous avez' join stat dans hourlyStats.DefaultIfEmpty() '. Utilisez-vous un autre ensemble de données ailleurs? – doctorless

+0

"var stats = ds.Tables [0] .AsEnumerable();" est les données tirées de sql db. var hourlyData effectue des fonctions d'agrégation sur cette table de statistiques. – mike

+0

Droit, mais regardez votre 'report ReportData = de l'heure en heures.AsEnumerable() rejoindre stat dans hourlyStats.AsEnumerable()'. Il dit 'hourlyStats', pas' hourlyData' – doctorless

0

Puisque vous faites une jointure gauche et que stat2 peut être nul, vous devrez gérer le cas où il peut être nul.

Essayez

select new 
{ 
    Hour = hour, 
    Value = hour, 
    D1 = stat2 != null ? stat2.D1 : 0, 
    D2 = stat2 != null ? stat2.D2 : 0, 
    D3 = stat2 != null ? stat2.D3 : 0 
}; 

REMARQUE: 0 pourrait ne pas être approprié dans votre cas; utilisez ce qui est approprié.