2009-05-21 6 views
0

Voici ce que je suis en train de faire:meilleure façon de Linq multiples jointures?

J'ai trois tables, manifestes, les détails et billingJournal

pour chaque manifeste il y a des détails et peut-être une entrée billingJournal ou non, s'il y a et il a le champ recordType = 1 puis billingJournal.amount est le montant de facturation et j'en ai besoin dans ma grille aussi.

Je suis actuellement en train de faire un processus en deux étapes:

  1. l'aide d'une jointure normale pour tirer ensemble un manifeste et ses détails, je retournais une vue simple DataGrid avec le code ci-joint basé sur un utilisateur daterange sélectionné .

  2. Je peux ensuite parcourir la grille de données avec une boucle. Je définis la boucle pour vérifier chaque ligne de la grille de données, lire le numéro du manifeste puis effectuer une recherche linq dans la table billingJournal. S'il y a une correspondance, il lit les données de la table billingJournal et récupère la valeur et la stocke dans la ligne actuelle des données. IE après regardant chacun des manifestes dans billingJournal, s'il y a une correspondance manifeste avec un record_type de 1 (un montant de facturation) alors je peux faire un simple remplacer comme:

BillingReportDataGrid (« montant », 1) .Value = queryResult

Ce que je voudrais savoir, y a-t-il un moyen de faire tout cela dans ma requête linq principale? Ou y a-t-il simplement une meilleure façon de le faire que la façon dont j'y vais? J'utilise une classe appelée rapportData afin que je puisse accéder aux colonnes par le nom.

J'ai essayé de jouer avec les jointures à gauche mais je n'arrive pas à l'obtenir.

Merci -

--Joe

Dim query = From detail In db.details _ 
       Where detail.InboundDate >= CType(MonthCalendar1.SelectionStart, DateTime) _ 
       And detail.InboundDate <= CType(MonthCalendar1.SelectionEnd, DateTime).AddHours(23).AddMinutes(59) _ 
       Join mainfest In db.Manifests On mainfest.ManifestID Equals detail.MainID _ 
       Select New reportData With {.Amount = Nothing, .ManifestID = mainfest.ManifestID, .InboundDate = detail.InboundDate} 
+0

« peut ensuite passer la grille de données avec une boucle, regarder chacun des manifestes dans billingJournal ... » Cela n'a pas de sens par rapport à la requête , car il n'est pas clair comment vous obtenez les données de billingjournal/où elles se trouvent, car votre requête ne les touche pas. Vous devriez mieux décrire ce que votre modèle est comme votre intro parle de 2 tables alors qu'il y en a clairement 3: les détails sont également impliqués. –

+0

Merci Frans - J'ai édité pour plus de contenu et de clarté ... Joe –

Répondre

0

Solution: Utilisation Soit assigner une variable le long d'une enbeded instruction if semble faire l'affaire (Merci à Fernado d'échange d'experts pour la prod .... utile)

Dim query = From detail In db.details _ 
      Where detail.InboundDate >= CType(MonthCalendar1.SelectionStart, DateTime) _ 
      And detail.InboundDate <= CType(MonthCalendar1.SelectionEnd, DateTime).AddHours(23).AddMinutes(59) _ 
      Join mainfest In db.Manifests On mainfest.ManifestID Equals detail.MainID _ 
      Let BillingQuery = (From b In db.Billings _ 
           Where b.ManifestID = mainfest.ManifestID _ 
           Order By b.RecordCreationDate Descending _ 
           Select b).First.Amount _ 
      Let BillingAmount = If(BillingQuery IsNot Nothing, Convert.ToDecimal(BillingQuery), Convert.ToDecimal(0.0)) _ 
      Select New reportData With {.olderDataExists = Nothing, _ 
             .Amount = Convert.ToDecimal(BillingAmount), _ 
             .ManifestID = mainfest.ManifestID, _ 
             .InboundDate = detail.InboundDate} 
1

Ce qu'il semble que vous voulez est fondamentalement une jointure externe à votre table billingJournal. Ce que vous recherchez est un opérateur appelé DefaultIfEmpty. Je ne peux pas publier de liens, mais si vous recherchez "Simuler un lien extérieur LINQ" sur Google, vous devriez trouver un exemple assez rapidement (celui de hookedonlinq est assez clair).

+0

Merci à vous deux - je vais faire une recherche et poster ici. David - je ne sais pas où est le problème, mais le code ne fonctionne pas dans mon compilateur - je vais poursuivre cette question plus loin ... –

2

Voici un exemple de ce dont Rick parle en simulant une jointure externe dans LINQ. Mon VB.Net est rouillé, mais je sais que cela fonctionne en C# très bien :)

Dim query = From detail In db.details _ 
       Where detail.InboundDate >= CType(MonthCalendar1.SelectionStart, DateTime) _ 
       And detail.InboundDate <= CType(MonthCalendar1.SelectionEnd, DateTime).AddHours(23).AddMinutes(59) _ 
       Join mainfest In db.Manifests On mainfest.ManifestID Equals detail.MainID into mainfestjoin _ 
       From submj in manifestjoin.DefaultIfEmpty() 
       Select New reportData With { _ 
           .Amount = Nothing, _ 
           .ManifestID = If submj <> Nothing Then mainfest.ManifestID Else 0 EndIf, _ 
           .InboundDate = detail.InboundDate} 
Questions connexes