Linq to sql - pb requête avec jointures [Résolu]

Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
- - Dernière réponse : leati24
Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
- 11 juin 2009 à 15:55
Bonjour,

Je développe une application en asp.net c#. J'utilise SQL Server pour stocker ma base de données et linq to sql pour accéder aux données.

Concrètement, j'ai trois tables : Personne (idPersonne, nomPersonne), Poste(idPoste, libPoste) et Travailler(idPersonne, idPoste). Je souhaiterais comme résultats les champs nomPersonne et libPoste. Pour ca j'utilise la requête suivante :

string reqSelect = "SELECT Personne.nomPersonne, Poste.libPoste FROM Personne
INNER JOIN Travailler ON Personne.idPersonne = Travailler.idPersonne
INNER JOIN Poste ON Travailler.idPoste = Poste.idPoste";

Et ensuite je l'exécute avec la méthode ExecuteQuery. Cependant, je ne sais pas quel type de retour indiqué puisque nomPersonne et libPoste ne forment pas un objet et ne sont pas dans la même table en base de données.

Auriez-vous des suggestions ?
Merci
Afficher la suite 

Votre réponse

12 réponses

Meilleure réponse
Messages postés
1863
Date d'inscription
lundi 28 novembre 2005
Dernière intervention
14 février 2015
3
Merci
Dans mon exemple, q a un type de retour, qui est ce qu'on appelle un type anonyme.

La solution la plus simple est de ne pas faire de cast : requete.ToList();
Cependant, si tu souhaites réutiliser les objets après, tu peux également faire une classe perso du genre
class MonEnsemble
{
    public LeTypeDeMaSource1 maSource1 {get; set;}
    public LeTypeDeMaSource2 maSource2 {get; set;}
    public LeTypeDeMaSource3 maSource3 {get; set;}
    public MonEnsemble(LeTypeDeMaSource1 source1, LeTypeDeMaSource2 source2, LeTypeDeMaSource3 source3)
    {
        maSource1 = source1;
        maSource2 = source2;
        maSource3 = source3;
    }
}

Et dans ta requête linq : IEnumerable<MonEnsemble> q = from ... in ... where ... select new MonEnsemble(a,b,c);

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 104 internautes ce mois-ci

Commenter la réponse de krimog
Messages postés
1863
Date d'inscription
lundi 28 novembre 2005
Dernière intervention
14 février 2015
0
Merci
Salut

Pourquoi utilises-tu une requête SQL si tu utilises Linq to SQL ???

            var q = from a in maSource1
                    from b in maSource2
                    from c in maSource3
                    where a.Id == b.Id
                    && a.Id == c.Id
                    select new
                    {
                        // C'est à ça que ressemblera ta sortie
                        Id = a.Id,
                        Machin = b.Machin,
                        Truc = c.Truc
                    };
            foreach (var element in q)
            {
                Console.WriteLine(element.Machin);
            }

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Commenter la réponse de krimog
Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
0
Merci
Je ne peux pas réellement utiliser de requête sous cette forme parce que j'ai des dizaines de paramètres dans ma fonction et je dois les inclure dans ma requête que s'ils ne sont pas égaux à "null"...
Commenter la réponse de leati24
Messages postés
1863
Date d'inscription
lundi 28 novembre 2005
Dernière intervention
14 février 2015
0
Merci
Où est le problème ?

where a.Id == b.Id
&& a.Id == c.Id&& (machin null || machin valeur)&& (bidule null || bidule.Propriete autreValeur)

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Commenter la réponse de krimog
Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
0
Merci
Le problème est que si mon paramètre est nul je ne veux pas le prendre en compte dans ma requête de sélection... Donc ma clause where vaudra dans le premier cas :

where a.Id = b.Id
&& a.Id = c.Id
&& parametre == valeur

et dans le deuxième cas :

where a.Id = b.Id

&& a.Id = c.Id

Et j'ai une dizaine de paramètres! Donc j'utilise une requête sql que je stocke dans un string et si mon paramètre n'est pas égal à null je l'ajoute dans la requête.
Commenter la réponse de leati24
Messages postés
1863
Date d'inscription
lundi 28 novembre 2005
Dernière intervention
14 février 2015
0
Merci
0) Désolé, problème de post...
1) N'oublie pas de doubler les = dans les conditions des requêtes Linq
2) J'ai parfaitement compris ton problème, tu ne sembles pas avoir compris ma solution

effectivement, faire
if (parametre != null)
{
...where a.Id == b.Id
&& a.Id == c.Id
&& parametre == valeur...
}else{
...where a.Id == b.Id
&& a.Id == c.Id...
}
avec une dizaine de paramètres, ça peut paraître long. Cependant, le code suivant fait EXACTEMENT la même chose :
...where a.Id == b.Id
&& a.Id == c.Id&& (parametre null || parametre valeur)...

En C#, les conditions sont traitées de gauche à droite. Il sort de la condition dès qu'il a assez d'éléments pour connaître la réponse (dans le cas d'un ||, il sort tout de suite si la première partie est vraie, ou passe à la deuxième sinon).
Donc si "parametre" est null, il passera directement à la suite. Sinon, il vérifiera si "parametre" est égal à "valeur".

Ce qui fait qu'avec 10 paramètres, on arrive à qqche du genre :

...where a.Id == b.Id
&& a.Id == c.Id

&& (param0 null || param0 valeur0)

&& (param1 null || param1 valeur1)

&& (param2 null || param2 valeur2)

&& (param3 null || param3 valeur3)

&& (param4 null || param4 valeur4)

&& (param5 null || param5 valeur5)

&& (param6 null || param6 valeur6)

&& (param7 null || param7 valeur7)

&& (param8 null || param8 valeur8)

&& (param9 null || param9 valeur9)...

Personnellement, ça ne me semble pas trop compliqué. Linq a été fait pour pas qu'on ait à utiliser du SQL, autant en profiter !
PS : si un paramêtre est d'un type non nullable, passé en nullable (int?, bool?, char?, double?...) tu devras remplacer paramX valeurX par paramX.value valeurX.

Krimog : while (!(succeed = try())) ;
- NON, "LE BAR" n'est PAS un langage de programmation ! -
Commenter la réponse de krimog
Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
0
Merci
Effectivement, je n'avais pas compris ta solution. Merci pour cette solution, je vais pouvoir ré-utiliser linq. Cependant, ca ne règle pas (tout à fait) mon problème initial.

Quand tu fais :
var q = from a in maSource1
                    from b in maSource2
                    from c in maSource3
                    where a.Id == b.Id
                    && a.Id == c.Id
                    select new
                    {
                        // C'est à ça que ressemblera ta sortie
                        Id = a.Id,
                        Machin = b.Machin,
                        Truc = c.Truc
                    };

la variable q n'a pas de type de retour puisque Id, machin et truc proviennent de trois tables différentes.
Je souhaite récupèrer cette sortie pour la mettre dans un gridView. Et donc la transformer en list (avec ToList<>()) pour pouvoir utiliser la pagination dans mon gridView (IEnumerable et IQueryable ne permet pas d'utiliser la pagination dans un gridView). Si je fais : return (q.ToList<?>()); par quoi je remplace le "?" dans ma fonction ?

J'ai trouvé une solution qui est d'écrire : (((IQueryable)requete).Cast<Object>().ToList<Object>()); Tu penses que c'est la meilleure solution ?

Merci de ton aide et désolée d'avoir un peu le cerveau lent
Commenter la réponse de leati24
Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
0
Merci
Si je mets pas le Cast<Object>(), j'ai une erreur de compilation : "Impossible de convertir implicitement le type 'System.Collections.Generic.List' en 'System.Web.UI.MobileControls.List'"

C'est effectivement la solution que j'avais trouvé (de créer une classe perso) mais je me demandais s'il n'y avait pas plus simple.

Merci beaucoup de ton aide très utile ;)
Commenter la réponse de leati24
Messages postés
6069
Date d'inscription
dimanche 13 avril 2003
Dernière intervention
15 juillet 2011
0
Merci
Salut,

Te permettra de supprimer le type anonyme

select new
MobileControls
                    {
Id =
a.Id,.....}

                    

Sinon tu peux empiler les requetes linq

var q = from c in source
....

var q2 = from d in q
            where ......

q2.ToList()

Mettre le toList au dernier moment pour que la requete SQL soit faite à ce moment.
Si non tu risques de raméné trop d'enregistement et les restriction des where se feront en linq2objet (ie en mémoire)

Bon dev
Commenter la réponse de nhervagault
Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
0
Merci
Merci nhervagault pour ta réponse, je vais également tester ca.

Krimog, je reviens vers toi parce que finalement ton exemple :
where a.Id == b.Id
&& a.Id == c.Id&& (machin null || machin valeur)&& (bidule null || bidule.Propriete autreValeur)

ne fonctionne pas. Je vais essayer d'être plus claire parce qu'en me relisant je trouve que je donne trop peu d'informations.

Sur ma page aspx, j'ai deux champs : champ1 et champ2 ainsi qu'un bouton rechercher. Lorsque l'utilisateur clique sur le bouton rechercher, champ1 et champ2 peuvent être vide. C'est dans ce cas que je souhaite ne pas les prendre en compte dans ma requête. C'est à dire, si champ1 et champ2 sont nuls :
where maTable1.id == maTable2.id

Si champ1 vaut "toto" et champ2 est toujours à vide par exemple, j'aurais la requête suivante :
where maTable1.id == maTable2.id
&& maTable1.champ = champ1
Ce qui veut dire que champ2 peut valoir toutes les valeurs qu'il souhaite : 'a', 'ahjkla', null, '+=)az'...

Toi tu m'aurais proposé d'écrire :
where maTable1.id == maTable2.id&& (maTable1.champ null || maTable1.champ ) ce qui me ramènerait seulement les enregistrements où maTable1.champ null.

J'espère avoir compris ce que tu me proposais. En tout cas, en testant dans mon code ca ne me retourne aucun enregistrement parce que aucun de mes champs sont null...
Commenter la réponse de leati24
Messages postés
9
Date d'inscription
samedi 2 juin 2007
Dernière intervention
27 juillet 2009
0
Merci
Je supprime mon dernier message. Tout fonctionne. Je n'exécute pas la bonne version :S
Commenter la réponse de leati24
Messages postés
1863
Date d'inscription
lundi 28 novembre 2005
Dernière intervention
14 février 2015
-1
Merci
Commenter la réponse de krimog

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.