Recuperer le resultat d'une requete dans une variable (linq)

Fermé
mimi19911980 Messages postés 22 Date d'inscription mardi 10 novembre 2020 Statut Membre Dernière intervention 14 octobre 2021 - 14 août 2021 à 01:23
 Utilisateur anonyme - 16 août 2021 à 19:02
Bonjour,

je veux récupérer le résultat d'une requête dans une variable comment le faire svp ???
j'ai essayer ca mais il me donne erreur :impossible d'effectuer un cast d'un objet de type:

sur cette ligne :



if (a == Convert.ToInt32(query1))


voici ma requête

   try
            {



                int a =Convert.ToInt32(cmbTypeLit.Text);
                   

               var  query1 =

                              from c in bdd.Lits
                              where c.occuper == false


                              select new
                              {
                                  c.numeroLit
                              };

                if (a == Convert.ToInt32(query1))
                {
                     
                    bdd.SaveChanges();
                    MessageBox.Show("Admission effectué avec succés");
                    bdd.Database.ExecuteSqlCommand("UPDATE Lits   SET occuper = 0  where  occuper=1 and numeroLit=(select numeroLit from Admissions) ");


                }
                else
                {
                    MessageBox.Show("lit occuper");

                }




quelqu'un peut m'aider svp??
Merci.

6 réponses

Utilisateur anonyme
14 août 2021 à 20:08
Une chose à la fois, la jointure n'était pas là la première fois, on en reparlera quand on aura solutionné le premier sujet

Bon je n'ai pas dû être assez explicite.

Une requête ça retourne une collection. Avec ou sans ToList. La différence c'est que sans ToList query1 sera de type IEnumerable<QuelqueChose>, avec ToList query sera de type List<QuelqueChose>.

Si QuelqueChose est du type int, query1 n'est pas du type int => tu ne peux pas le convertir.
Par contre, chaque élément de query1 est du type int, donc il faut en "choisir" un.
Pour mon exemple, j'ai choisi de caster en List<int> pour 3 raisons
  • Linq exécute vraiment la requête au moment où le code en a besoin, pas là où elle est écrite. Quand on débute avec Linq (ce qui est manifestement le cas) ça peut apporter plus de problèmes que d'avantage. Une fois castée en List la collection est figée.
  • Il n'y a pas de propriété Count dans le type IEnumerable, parce que pour connaitre le nombres d'éléments, il faut exécuter or, comme je te l'ai dit juste avant, elle n'est exécutée qu'au moment il y a en a besoin. Il y a donc une méthode Count() qui exécute la requête et en compte les éléments. Donc List .Count, IEnumerable .Count() ça peut porter à confusion quand on débute.
  • On ne peut pas prendre directement un élément dans un IEnumerable (toujours parce que la requête n'est pas exécutée), il y a une méthode ElementAt(int Index) qui exécute la reqûete et retourne l'élément à l'index indiqué. Mais comme on vient déjà d'éxécuter la requête pour le count et bien on le fait 2 fois de suite pour pas grand chose, il y a perte de temps d'exécution et gâchis de ressources


En castant en Lis<int>, la requête n'est exécutée qu'une seule fois, la propriété Count est disponible directement ainsi que chaque élément.

Je ne t'a pas expliqué tout ça craignant te submerger d'informations.


Ensuite
mais dans ce cas il me prend toujours le premier enregistrement de ma table Lits
alors 2 choses.
  • Pour mon exemple, j'ai choisi d'extraire le premier élément de la requête, rien ne t'empêche de choisir le 17eme, s'il y en a au moins 17 bien sûr.
  • Si cette requête te retourne en premier élément le premier numéro de lit de ta table, qui en théorie est occupé (sans r) alors le problème ne vient pas de cette requête mais très probablement de la collection bdd.Lits. Pour en avoir la confirmation, il faut que tu mettes un point d'arrêt, que tu espionnes les éléments de bdd.Lits pour trouver celui qui a le premier numéro et vérifier la valeur de la propriété "occuper" (qui à mon avis n'est pas renseignée comme il faut).


1
Utilisateur anonyme
16 août 2021 à 19:01
Je ne suis pas sûr de comprendre ta dernière demande.

Mais si je l'ai comprise, alors c'est que décidément je n'ai pas été assez clair...

Je vais donc utiliser une parabole.

Supposons que notre collection d'origine soit un jeux de 52 cartes, et que la requête demande de selection les cartes noires. Il va y en avoir 36. Si parmi ces cartes noires, il faut en choisir une, il alors est nécessaire de preciser laquelle. (je veux la 12 eme par exemple)

Dans mon exemple, c'est le premier lit qui est choisi, par query1[0], par ce que c'est le plus simple. Si il y plus que 0 lits alors y'en a au moins 1. Si on veut prendre le 20eme, il faut vérifier qu'il y en a au moins 20 et si c'est pas le cas faire un nouveau choix, qui lui aussi pourraient entrainer un autre choix etc....

Il est possible de retourner directement, le premier ou le dernier élément d'une collection avec les méthodes First() et Last()
                int premier = (from c in bdd.Lits
                              join k in bdd.Admissions on c.numeroLit equals k.numeroLit
                              where c.occuper == false
                              select c.numeroLit
                                          ).First();

                int dernier = (from c in bdd.Lits
                              join k in bdd.Admissions on c.numeroLit equals k.numeroLit
                              where c.occuper == false
                              select c.numeroLit
                                          ).Last();


Mais ces 2 requêtes vont planter ton programme s'il n'y a plus de list disponibles, car First() et Last() partent du principe que la collection "appelante" n'est pas vide.

Ce serait pareil si de mon jeu de cartes, je demandais les cartes jaunes
=> y'en a pas, la requête retourne une collection vide, et ça ne plante pas.
Mais si je demande la première ou la dernière carte jaune => ça plante.

Pour éviter cela, il y a FirstOrDefault et LastOrDefault, mais là encore ce n'est pas parfait.
Pour mon jeux de cartes, si je demande la première ou défault carte jaune, ça va retourner la valeur par défaut d'une classe => null et derrière ça plantera parce que ma carte est nulle...

Dans le cas d'un int, la valeur par défaut c'est 0, mais là encore c'est pas cool, car un de tes lits pourrait être numéroté 0 et tu aurais donc une mauvaise attribution.

                int premier = (from c in bdd.Lits
                              join k in bdd.Admissions on c.numeroLit equals k.numeroLit
                              where c.occuper == false
                              select c.numeroLit
                                          ).FirstOrDefault();

                int dernier = (from c in bdd.Lits
                              join k in bdd.Admissions on c.numeroLit equals k.numeroLit
                              where c.occuper == false
                              select c.numeroLit
                                          ).LastOrDefault();

              if(premier == 0)
                     MessageBox.Show("On ne sait pas si le lit 0 est occupé.....");

              if(dernier == 0)
                     MessageBox.Show("On ne sait pas si le lit 0 est occupé.....");




1
Utilisateur anonyme
16 août 2021 à 19:02
Bref, le plus simple et le plus sûr c'est de vérifier le nombre de lits récupérés par ta requête et s'il ne vaut pas 0 de prendre le premier.
0
Utilisateur anonyme
14 août 2021 à 07:54
Bonjour

cette requête retourne une collection d'objets anonyme dont une propriété est un int.
Cela fait 2 bonnes raisons pour que tu ne puisses pas convertir query1 en int.
  • une collection n'est pas un int
  • les éléments de cette collection ne sont pas des int


Ici l'utilisation du type anonyme ne sert à rien, puisqu'il n'y a qu'une propriété

Tu dois
  • supprimer le type anonyme
  • vérifier s'il y a au moins un élément
  • dans l'affirmative en choisir un et le convertir.


Par exemple
//requête sans type anonyme
var  query1 =(from c in bdd.Lits
                           where c.occuper == false
                           select c.numeroLit
                           ).ToList();
//le ToList permet d'utiliser query1 comme une List<int> et pas comme un IEnumerable<int> c'est plus simple et manifestement tu n'as pas besoin de l'exécution décalée de linq

//vérification qu'il y a au moins un résultat
if (query1.Count > 0)
     int b = Convert.ToInt32(query1[0]); //conversion du premier élément de la collection, 
else
    throw new Exception("aucun lit disponibles");

0
mimi19911980 Messages postés 22 Date d'inscription mardi 10 novembre 2020 Statut Membre Dernière intervention 14 octobre 2021
14 août 2021 à 18:28
mais dans ce cas il me prend toujours le premier enregistrement de ma table Lits
j'ai modifier ma requête j'ai fait une jointure a fin de récupérer un seul résultat. et j'ai enlever le .toList, Mais ca marche pas toujours, j'ai toujours exception impossible de convertir un type query en int

 try
            {
                var query1 = (from c in bdd.Lits
                              join k in bdd.Admissions on c.numeroLit equals k.numeroLit
                              where c.occuper == false
                              select c.numeroLit
                                           );
         

                 int a = Convert.ToInt32(cmbTypeLit.Text);


                int b = Convert.ToInt32(query1);

                if (b == a)

                {
                    MessageBox.Show("le lit est occuper");


                }
                else
                {


                    bdd.SaveChanges();
                    MessageBox.Show("Admission effectué avec succés");
                    bdd.Database.ExecuteSqlCommand("UPDATE Lits   SET occuper = 0  where  occuper=1 and numeroLit=(select numeroLit from Admissions) ");




                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);

            }




0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mimi19911980 Messages postés 22 Date d'inscription mardi 10 novembre 2020 Statut Membre Dernière intervention 14 octobre 2021
16 août 2021 à 17:48
Merci pour votre c'est reglé:

voici le code:


 try
            {
                //int a = Convert.ToInt32(cmbTypeLit.Text);
              //int a=  (cmbTypeLit.SelectedItem as Lit).numeroLit;

                var query1 = (from c in bdd.Lits
                              join k in bdd.Admissions on c.numeroLit equals k.numeroLit
                              where c.occuper == false
                              select c.numeroLit
                                          ).ToList();
                int a = Convert.ToInt32(cmbTypeLit.Text);
                if (query1.Count > 0) { 
                    int b = Convert.ToInt32(query1[0]);

                    if (a != b)
                    {

                        bdd.Admissions.Add(ad);

                        bdd.SaveChanges();
                        MessageBox.Show("Admission effectué avec succés");
                        bdd.Database.ExecuteSqlCommand("UPDATE Lits   SET occuper = 0  where  occuper=1 and numeroLit in (select numeroLit from Admissions) ");
                    }

                    else
                    {

                        {
                            MessageBox.Show("le lit est occuper");


                        }
                    }
                }


                    
                
 
                   
                   
                
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);

            }


0
mimi19911980 Messages postés 22 Date d'inscription mardi 10 novembre 2020 Statut Membre Dernière intervention 14 octobre 2021
16 août 2021 à 17:54
svp comment le rendre d'une manière automatique au lieu de préciser query1[0]
il va se faire automatiquement. Car ici la condition s'applique juste pour le premier Lits enregistrer dans la base de donner

merci
0