Précédent   Forum des professionnels en informatique > Dotnet > Accès aux données > Linq
Linq Forum d'entraide sur la manipulation de données avec Linq
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/10/2011, 10h26   #1
Membre éclairé
 
Homme
Développeur Sharepoint/Biztalk
Inscription : octobre 2008
Messages : 501
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur Sharepoint/Biztalk

Informations forums :
Inscription : octobre 2008
Messages : 501
Points : 399
Points : 399
Par défaut Join multiple linq et dataset

Bonjour,

Je rencontre un gros soucis, sur lequel je bloque depuis quelques heures ..

J'ai un dataset qui comporte 4 tables. J'ai une table principale qui comporte des éléments (dont une clé primaire) et 3 tables annexes. Les 3 tables sont indépendantes mais comportent des caractéristiques par rapport à la clé primaire de la table principale.

J'aimerais faire une requête qui récupére tous les enregistrements où
table1.cléprimaire = table2.ID && ( || ?)
table1.cléprimaire = table3.ID && ( || ?)
table1.cléprimaire = table4.ID && ( || ?)

J'ai tenté cette requête :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var requete = from A in table1.AsEnumerable()
                          //from C in table3.AsEnumerable()
                          join B in table2.AsEnumerable()
                             on A["TPLNR"] equals B["TPLNR"]
                          join C in table3.AsEnumerable()
                             on A["TPLNR"] equals C["TPLNR"]
                          //where A["TPLNR"] == B["TPLNR"] || A["TPLNR"] == C["TPLNR"]
                          join D in table4.AsEnumerable()
                             on A["TPLNR"] equals D["TPLNR"]
                          select new
                          {
                              BEBER = A.Field<string>("BEBER"),
                              EVENT = A.Field<string>("EVENT"),
                              UNIT_FROM = B.Field<string>("UNIT_FROM"),
                              VALUE_FROM = C.Field<string>("VALUE_FROM")
                          };
Cependant cela me retourne 0 enregistrement. Par contre si je laisse seulement une seule jointure entre A et B, ca fonctionne .. c'est la jointure multiple qui fonctionne pas

En sql je sais faire, mais j'ai du mal à traduire :/ J'ai regardé beaucoup de tuto, mais souvent pas de join multiple, ou alors leur solution ne fonctionne pas chez moi, je dois louper une étape ..

Merci !
bob633 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 11h09   #2
Responsable .NET
 
Avatar de tomlev
 
Homme Thomas Levesque
Développeur .NET
Inscription : février 2004
Messages : 16 721
Détails du profil
Informations personnelles :
Nom : Homme Thomas Levesque
Âge : 30
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2004
Messages : 16 721
Points : 26 694
Points : 26 694
Est-ce que la clé existe dans toutes les tables ? S'il y a ne serait-ce qu'une table où elle n'existe pas, ça ne renvoie rien pour cette clé... Ou alors il faut faire une jointure externe
__________________

Pas de questions techniques par MP ! Le forum est là pour ça...

Tutoriels : Les markup extensions en WPF - La sérialisation XML avec .NET (Aller plus loin) - Une visite guidée de WPF (traduction)
Projet : Dvp.NET, la librairie .NET open-source des membres de Developpez !

Envie de contribuer à la rubrique .NET ?
tomlev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 11h36   #3
Membre éclairé
 
Homme
Développeur Sharepoint/Biztalk
Inscription : octobre 2008
Messages : 501
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur Sharepoint/Biztalk

Informations forums :
Inscription : octobre 2008
Messages : 501
Points : 399
Points : 399
Oui la clé existe dans toute les tables

Cependant il se peut que pour un élément dans la table principale, une table ne retourne rien.

Pour expliquer plus le contexte, j'ai un événement dans la table principale. Cet événement comporte diverses caractéristiques. Ces caractéristiques peuvent être de type numérique, caractère etc. En fait pour un type, on a une table annexe (connexion avec SAP donc pas le choix).

Cependant je pense que SQL gère très bien le fait que s'il trouve rien dans une table, il passe au reste.

Cependant c'est la première fois que j'utilise linq, et je remarque que les jointures multiples sont pas si simple qu'en SQL (enfin quand une fonctionnera ca ira mieux ).

edit : il y a du nouveau. En fait ca fonctionne sauf que lui il fait le lien entre les jointures comme du ET. Sauf que moi il faudrait des jointures en OU. Tu vois ? Comment je peux faire ca sur du join ?

Merci
bob633 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 14h03   #4
Responsable .NET
 
Avatar de tomlev
 
Homme Thomas Levesque
Développeur .NET
Inscription : février 2004
Messages : 16 721
Détails du profil
Informations personnelles :
Nom : Homme Thomas Levesque
Âge : 30
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2004
Messages : 16 721
Points : 26 694
Points : 26 694
Citation:
Envoyé par bob633 Voir le message
Cependant il se peut que pour un élément dans la table principale, une table ne retourne rien.
Oui, c'est ça que je voulais dire


Citation:
Envoyé par bob633 Voir le message
Cependant je pense que SQL gère très bien le fait que s'il trouve rien dans une table, il passe au reste.
Sans doute parce qu'en SQL tu as fait une jointure externe

Citation:
Envoyé par bob633 Voir le message
edit : il y a du nouveau. En fait ca fonctionne sauf que lui il fait le lien entre les jointures comme du ET. Sauf que moi il faudrait des jointures en OU. Tu vois ? Comment je peux faire ca sur du join ?
Comme je t'ai dit plus haut, il faut une jointure externe.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
            var requete = from A in table1.AsEnumerable()
                          join B in table2.AsEnumerable()
                             on A["TPLNR"] equals B["TPLNR"] into tmp2
                             from B in tmp2.DefaultIfEmpty()
                          join C in table3.AsEnumerable()
                             on A["TPLNR"] equals C["TPLNR"] into tmp3
                             from C in tmp3.DefaultIfEmpty()
                          join D in table4.AsEnumerable()
                             on A["TPLNR"] equals D["TPLNR"] into tmp4
                             from D in tmp3.DefaultIfEmpty()
                          select new
                          {
                              BEBER = A.Field<string>("BEBER"),
                              EVENT = A.Field<string>("EVENT"),
                              UNIT_FROM = B =! null ? B.Field<string>("UNIT_FROM") : null,
                              VALUE_FROM = C != null ? C.Field<string>("VALUE_FROM") : null
                          };
__________________

Pas de questions techniques par MP ! Le forum est là pour ça...

Tutoriels : Les markup extensions en WPF - La sérialisation XML avec .NET (Aller plus loin) - Une visite guidée de WPF (traduction)
Projet : Dvp.NET, la librairie .NET open-source des membres de Developpez !

Envie de contribuer à la rubrique .NET ?
tomlev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 14h15   #5
Membre éclairé
 
Homme
Développeur Sharepoint/Biztalk
Inscription : octobre 2008
Messages : 501
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur Sharepoint/Biztalk

Informations forums :
Inscription : octobre 2008
Messages : 501
Points : 399
Points : 399
Merci bien ca marche du feu !

Par contre j'ai un peu de mal avec les expressions "jointures externes" et "jointures internes", et sur google ca me parle de jointure gauche interne, jointure droite externe .. je me perd un peu ? C'est pour comprendre tes lignes de jointures avec les clause defaultIfEmpty() ..


edit : j'ai crié victoire trop vite .. J'ai fais mes tests voir ce que je récupérais exactement de ca. Le problème arrive lorsque pour un événement principal (table principale), il existe des caractéristiques dans au moins deux des trois autres tables, il me créé un seul enregistrement en prenant la valeur dans chacun des tables (en gros au lieu de faire un enregistrement pour la 1ere caractéristique, puis un deuxième pour la 2eme caractéristique, il prend les deux champs pour le même.

Travaillant sur un projet pour faire communiquer deux applications, il est nécessaire d'avoir deux lignes distinctes :/ bien que ca peut faire redondance ...

Je pense qu'il doit exister une condition qui permet de dire, si une des valeurs existe, alors l'autre est nulle :/ Mais j'ai peur d'alourdir énormément ma requête, et je sais pas si c'est possible directement dans le select (mes essais sont pas très concluant).

Encore merci.
bob633 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 14h57   #6
Membre éclairé
 
Homme
Développeur Sharepoint/Biztalk
Inscription : octobre 2008
Messages : 501
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur Sharepoint/Biztalk

Informations forums :
Inscription : octobre 2008
Messages : 501
Points : 399
Points : 399
Finalement j'ai compris le principe des DefaultIfEmpty, en fait on passe la main de table en table pour voir .. mais peut-on créer des enregistrements différents, même lorsqu'il trouve des correspondances entre plusieurs tables ?

edit : En fait je me suis fait un jeu de test.
Admettons 4 tables :

A B C D

v1 v1 v2 v1
v2 v2 v2 v2

Résultat :
v1 v1
v1 v1
v2 v2 v2 v2
v2 v2 v2 v2
En gros il différencie pas qu'il y a qu'une valeur dans B puis 2 dans C etc Au final il réplique autant de fois que la table où il y en aura le plus. Sauf que le logiciel d'arrivé ne saura pas gérer ..

Je pensais peut-être faire ensuite un traitement pour séparer les lignes mais bon là c'est complexe et "usine à gaz".
bob633 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 15h13   #7
Responsable .NET
 
Avatar de tomlev
 
Homme Thomas Levesque
Développeur .NET
Inscription : février 2004
Messages : 16 721
Détails du profil
Informations personnelles :
Nom : Homme Thomas Levesque
Âge : 30
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2004
Messages : 16 721
Points : 26 694
Points : 26 694
Citation:
Envoyé par bob633 Voir le message
edit : j'ai crié victoire trop vite .. J'ai fais mes tests voir ce que je récupérais exactement de ca. Le problème arrive lorsque pour un événement principal (table principale), il existe des caractéristiques dans au moins deux des trois autres tables, il me créé un seul enregistrement en prenant la valeur dans chacun des tables (en gros au lieu de faire un enregistrement pour la 1ere caractéristique, puis un deuxième pour la 2eme caractéristique, il prend les deux champs pour le même.
Ah ok... j'avais pas bien compris ce que tu voulais alors. Tu peux montrer à quoi ressemblait ta requête SQL d'origine ? ce sera plus clair
__________________

Pas de questions techniques par MP ! Le forum est là pour ça...

Tutoriels : Les markup extensions en WPF - La sérialisation XML avec .NET (Aller plus loin) - Une visite guidée de WPF (traduction)
Projet : Dvp.NET, la librairie .NET open-source des membres de Developpez !

Envie de contribuer à la rubrique .NET ?
tomlev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 15h21   #8
Membre éclairé
 
Homme
Développeur Sharepoint/Biztalk
Inscription : octobre 2008
Messages : 501
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur Sharepoint/Biztalk

Informations forums :
Inscription : octobre 2008
Messages : 501
Points : 399
Points : 399
Je suis directement passé par Linq en fait.

J'ai 4 tables : A, B, C et D

A se trouve au centre. B, C et D ont dont une clé étrangère de A.

En fait la requête doit d'abord chercher les valeurs entre A et B, puis entre A et C, puis entre A et D où B, C et D sont complétement indépendants en fait.

Je pense qu'en SQL normal ca devrait ressembler à :
Code :
1
2
select A.beber, B.unit_from, C.unit_char from A, B, C
where A.id == B.idCE || A.id == C.idCE ;
J'ai pas testé donc je sais pas si ça fonctionnerait le fait de faire des "OU" entre les id mais l'idée est là, on pioche dans les autres tables.

Je sais pas si j'arrive à expliquer :/
bob633 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 17h07   #9
Responsable .NET
 
Avatar de tomlev
 
Homme Thomas Levesque
Développeur .NET
Inscription : février 2004
Messages : 16 721
Détails du profil
Informations personnelles :
Nom : Homme Thomas Levesque
Âge : 30
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2004
Messages : 16 721
Points : 26 694
Points : 26 694
En fait, l'instruction join de Linq correspond à une équijointure. Le code SQL que tu montres réalise une jointure cartésienne et filtre les résultats ensuite. Pour faire l'équivalent avec Linq, il faut faire quelque chose comme ça :

Code :
1
2
3
4
5
6
7
8
9
10
11
var requete = from A in table1.AsEnumerable()
              from B in table2.AsEnumerable()
              from C in table3.AsEnumerable()
              where A.Field<int>("TPLNR") == B.Field<int>("TPLNR") || A.Field<int>("TPLNR") == C.Field<int>("TPLNR")
              select new
              {
                  BEBER = A.Field<string>("BEBER"),
                  EVENT = A.Field<string>("EVENT"),
                  UNIT_FROM = B =! null ? B.Field<string>("UNIT_FROM") : null,
                  VALUE_FROM = C != null ? C.Field<string>("VALUE_FROM") : null
              };
(note l'utilisation de la méthode Field à la place de l'indexeur ; si tu utilises l'indexeur, ça renvoie un object, et l'opérateur == fera donc une comparaison de référence, ce qui n'est pas le comportement souhaité)
__________________

Pas de questions techniques par MP ! Le forum est là pour ça...

Tutoriels : Les markup extensions en WPF - La sérialisation XML avec .NET (Aller plus loin) - Une visite guidée de WPF (traduction)
Projet : Dvp.NET, la librairie .NET open-source des membres de Developpez !

Envie de contribuer à la rubrique .NET ?
tomlev est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/10/2011, 16h39   #10
Membre éclairé
 
Homme
Développeur Sharepoint/Biztalk
Inscription : octobre 2008
Messages : 501
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Pyrénées Atlantiques (Aquitaine)

Informations professionnelles :
Activité : Développeur Sharepoint/Biztalk

Informations forums :
Inscription : octobre 2008
Messages : 501
Points : 399
Points : 399
Parfait, c'est ce que je cherchais =)

Merci beaucoup
bob633 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 11h27.


 
 
 
 
Partenaires

Hébergement Web