Partage
  • Partager sur Facebook
  • Partager sur Twitter

asp// c# /mvc//erreur requete linq

requetes Linq//impossible à voir le resultat dans la vue

7 avril 2017 à 13:30:24

Bonjour,

Je travaille sur les requetes Linq, voici ma requete je pense pas avoir d'erreur de syntaxe,

public ActionResult test()
        {
            SampleEntities1 db = new SampleEntities1();
            var recupEmployes = (from d in db.Department
                                join e in db.Employee
                                on d.Id equals e.DepartmentId                              
                                orderby e.EmployeeId
                                select new {d.Name,e.City,}).ToList();
            return View(recupEmployes);
        }

Le message est: 

Erreur du serveur dans l'application '/'.


L'élément de modèle passé dans le dictionnaire est de type « System.Collections.Generic.List`1[<>f__AnonymousType5`2[System.String,System.String]] », mais ce dictionnaire requiert un élément de modèle de type « System.Collections.Generic.IEnumerable`1[linqSQL.Employee] ».

Merci



-
Edité par ellyse 7 avril 2017 à 22:00:03

  • Partager sur Facebook
  • Partager sur Twitter
7 avril 2017 à 16:58:57

Hello,

L'erreur est assez explicite, ta vue attend un élément de type IEnumerable<linqSQL.Employee>, or ta requête renvoi un type anonyme, var c'est pratique mais l'utiliser quand on n'est pas sûr de ce qui est renvoyé est une mauvaise idée puisqu'on tombe assez vite dans ce genre d'erreurs.

Il faut que ta query renvoi une collection de linqSQL.Employee au lieu de ce type anonyme ;)

  • Partager sur Facebook
  • Partager sur Twitter
Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
7 avril 2017 à 17:06:50

Hello,

Merci, alors 2 choses, 

1. Ce pb je le rencontre seulement quand je fais une jointure, dans cette autre requete j'ai pas ce pb, pourquoi? Est ce pcq là c'est pas une liste? Pourtant dans la vue je la crée en mode "liste"

//requete linq
        public ActionResult employesLinq()
        {
            SampleEntities1 db = new SampleEntities1();
            var q= from Employee in db.Employee
                                where Employee.Gender == "Male"
                                orderby Employee.Name
                                select Employee;
            return View(q);
        }



2. J'ai compris mon erreur mais comment ma query peut renvoyer une collection de linqSQL, tu peux me montrer ou me corriger mon code niveau de la syntaxe que j'apprenne?...

Merci 

-
Edité par ellyse 7 avril 2017 à 17:10:16

  • Partager sur Facebook
  • Partager sur Twitter
7 avril 2017 à 17:58:08

J'ai l'impression que tu ne comprends pas suffisamment ce que tu fais, c'est pas grave en soi mais ça mérite quelques explications.

  • Ici, ton select récupére un "Employee", c'est un type connu dans ton modèle, pas de soucis pour Entity Framework ou quelque soit l'ORM que tu utilises, quand la base SQL va lui renvoyer les champs, il sait qu'il doit créer un objet Employee et le construire avec les valeurs récupérées depuis la requête. Il ne faut pas oublier que ta requête va être envoyée à la base de donnée et que ici, tu fais l'équivalent d'un select sur tous les champs de la table Employee. Quand le résultat revient, il crée un nouvel objet Employee et te le renvoi, var correspond donc à Employee.
  • Tu fais une jointure mais ce n'est pas le problème, le problème est dans ton select new { ... }, c'est une facilité offerte par C# de pouvoir créer des objets de type anonyme, comprendre, sans type connu. C'est très pratique quand on se fiche un peu d'où viennent les propriétés qu'on associe dans ce nouvel objet mais toi c'est tout le contraire, tu as un modèle connu et les différentes valeurs que tu récupères de ta base de données ont toutes un sens. Tu récupère des Employee et leur Department, contrairement à ton objet anonyme, qu'Entity Framework ne connaît pas, il connaît Employee et Department, il sait qu'un Employee a un Department et qu'un Department contient plusieurs Employee. Il t'a sûrement généré un Modèle qui ressemble à ça:
        public class Employee
        {
            public int Id { get; set; }
            public int DepartmentId { get; set; }
            public string Name { get; set; }
            public string Gender { get; set; }
            public string City { get; set; }

            public virtual Department Department { get; set; }
        }

        public class Department
        {
            public int Id { get; set; }
            public string Name { get; set; }

            public virtual ICollection<Employee> Employees { get; set; }
        }

        Il suffit de t'en servir au lieu de t'amuser avec les types anonymes, tout est déjà prévu pour. Ta jointure explique déjà à la base de données qu'elle doit te renvoyer les infos à la fois de Department et d'Employee, tu as donc toutes les infos qu'il te faut pour remonter une liste d'Employee qui contiendra pour chacun son Department.

var employees = (from e in db.Employee
                 join d in db.Department
                 on e.DepartmentId equals d.Id
                 orderby e.Id
                 select e).ToList();

Et ton var correspondra ici à une liste d'Employee ce qui est bien ce que ton modèle demande, ton type anonyme ne remontait que deux colonnes, ce qui était très insuffisant par rapport à toutes les valeurs que demande ta vue. Attention donc avec var, C# est fortement typé et abuser de var porte plus à confusion qu'autre chose, si tu passes la souris sur ton var, Visual Studio est capable de te dire ce qu'il deviendra dans ton programme, mais il est mieux d'être explicite quand il y en a besoin plutôt que d'utiliser var à tout bout de champ ;)

PS : J'ai changé un peu la requête, je trouve ça plus clair de faire la jointure dans ce sens là vu qu'on demande une liste d'Employee et pas de Department.

-
Edité par Pyrobolser 7 avril 2017 à 18:14:06

  • Partager sur Facebook
  • Partager sur Twitter
Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
7 avril 2017 à 20:18:17

ok merci pour l'explication, j'ai compris.

J'ai une autre demande mais je sais pas si je dois créer un nouveau sujet.

Je voudrais m’entraîner sur ces requêtes linq d'avantages. Par exemple, dans ma requête utiliser des IN/SUBSTR/LIKE/LENGTH/BETWEEN etc

donc adapter ces types de requetes 

// Select * from employee where name in ('elise','léa').

//select * from employee  where city LIKE 'a%'

à des requêtes Linq avec des jointures etc. Je voudrais un tuto ou quelque chose comme ça.

-
Edité par ellyse 7 avril 2017 à 20:19:18

  • Partager sur Facebook
  • Partager sur Twitter
7 avril 2017 à 21:26:27

101 Linq Samples est très chouette :)
  • Partager sur Facebook
  • Partager sur Twitter
Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
7 avril 2017 à 21:35:01

merci, par contre j'ai pas résolu le pb précédent. D'après ce que j'avais compris, j'ai recrée une classe Employee.cs dans le dossier Models, puis recrée la vue avec la boite de dialogue précisant le: Model: List// Classe de Model:Employee(linqSQL.Models) et toujours la même erreur. Peut ^tre que j'ai rien compris :s

Par contre le lien 101 Linq est top merci

namespace linqSQL.Models
{
    public class Employee
    {
        public int EmployeeId { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public string City { get; set; }
        public int DepartmentId { get; set; }
    }
}

@model IEnumerable<linqSQL.Models.Employee>

@{
    ViewBag.Title = "testBis";
}

<h2>testBis</h2>
...



-
Edité par ellyse 7 avril 2017 à 21:37:39

  • Partager sur Facebook
  • Partager sur Twitter
7 avril 2017 à 21:41:34

Euh oula non, le modèle c'est pas à toi de le créer, ton ORM (Entity Framework, etc.) à du le créér lui même.

Si tu changes ta requête par la mienne ça devrait suffire à tout faire fonctionner, par contre si tu ne la comprend pas ou si tu as d'autres questions hésites pas à être plus précise dans tes demandes pour bien comprendre.

  • Partager sur Facebook
  • Partager sur Twitter
Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
7 avril 2017 à 21:59:36

oui je sais que entity framework le crée lui même mais en lisant sur internet certains disaient que c'est mieux de créer le model etc bref.

En faite, ta requête à toi fonctionne et fonctionnait même avant, mais la requête dont je te montre moi ne fonctionne pas (peu importe l'ordre des tables)et c'est dessus que j'ai l'erreur en question! 

public ActionResult test()
        {
            SampleEntities1 db = new SampleEntities1();         
            var employees = (from d in db.Department
                     join e in db.Employee
                     on d.Id equals e.DepartmentId
                     orderby e.Id
                     select new {e.Name, e.City }).ToList();
            return View(employees);
        }

Le pb est au niveau de la ligne 'select' je pense (je veux afficher le nom et la ville)

Et sinon en soit la requête et ce qu'elle fait (notamment au niveau de la jointure des clé etc) je la comprends très bien donc pas de question dessus.

-
Edité par ellyse 7 avril 2017 à 22:04:54

  • Partager sur Facebook
  • Partager sur Twitter
7 avril 2017 à 22:05:12

Ça confirme ce que je dis, tu lis mais tu ne comprends pas.

Ton select renvoi une nouvelle liste de "objet anonyme" qui contient un Name et une City.

Mon select renvoi une nouvelle liste de "Employee".

La vue vers laquelle il renvoi attend une liste d'Employee, pas une liste de "objet anonyme".

C'est ton select le problème, relis mon message et dis moi ce qui coince.

  • Partager sur Facebook
  • Partager sur Twitter
Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
9 avril 2017 à 15:57:25

mais si j'ai compris ce que tu dis, c'est ma requête que j'arrive pas à l'adapter, car je souhaite par exemple que visuellement ça affiche seulement la colonne 'city' et "name" aussi , et non pas toutes les colonnes comme id, name,gender city etc
  • Partager sur Facebook
  • Partager sur Twitter
10 avril 2017 à 4:50:57

Il faut changer la vue dans ce cas là.
  • Partager sur Facebook
  • Partager sur Twitter
Si un message vous a aidé, n'oubliez pas le +1 et de passer votre sujet en "Résolu" ! :)
6 mars 2020 à 16:06:25 - Message modéré pour le motif suivant : Merci d'utiliser le bouton code du forum pour insérer votre code


6 mars 2020 à 16:12:00

Bonjour,

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter