2010-03-15 4 views
5

Je voudrais implémenter MVC en utilisant LINQ (spécifiquement, LINQ-to-entities). La façon dont je ferais ceci est que le contrôleur génère (ou appelle quelque chose qui génère) le jeu de résultats en utilisant LINQ, puis le renvoie à la vue pour afficher les données. Le problème est, si je fais:Un moyen simple de renvoyer des types anonymes (pour rendre MVC possible avec LINQ)

return (from o in myTable select o); 

Toutes les les colonnes sont lues à partir de la base de données, même celles (potentiellement des dizaines) je ne veux pas. Et - plus important encore - je ne peux pas faire quelque chose comme ceci:

return (from o in myTable select new { o.column }); 

parce qu'il n'y a aucun moyen de faire le type de sécurité de types anonymes! Je sais avec certitude qu'il n'y a pas de manière agréable et propre de faire cela en 3.5 (this n'est pas propre ...), mais qu'en est-il de la version 4.0? Y a-t-il quelque chose de prévu, ou même de proposé? Sans quelque chose comme duck-typing-for-LINQ, ou des valeurs de retour anonymes sécurisées (il me semble que le compilateur devrait certainement en être capable), il semble presque impossible de séparer proprement le Controller de la View.

+0

Lorsque vous travaillez avec un orm, vous devez vous habituer à ce que sql sélectionne toutes les colonnes d'une table. Si vous écrivez des requêtes qui n'en sélectionne que quelques-unes, vous pourriez tout aussi bien utiliser sql en premier lieu. Si vous avez des dizaines de propriétés sur vos objets, c'est votre problème. Vos objets devraient être plus petits et vous devriez réfléchir à comment vous pouvez résoudre ce problème. Les types anonymes ne doivent pas être transmis, spécialement pas comme des modèles à une vue. –

+0

@Mattias: Malheureusement, la vie n'est pas si simple. Par exemple, considérons le cas où je sélectionne quelques colonnes de différentes tables, y compris un tableau d'objets sélectionnés à l'aide d'une requête interne LINQ. Autant que je sache, il n'y a aucun moyen de retourner cela comme un seul objet EF - il doit * être * un nouveau type, et définir un nouveau type concret pour chaque requête comme celle-ci est ridiculement lourd. –

+0

On dirait que vous avez un très mauvais modèle. Votre objet doit avoir les références dont il a besoin et vous pouvez simplement utiliser la méthode "Include()" dans EF (pour charger avec impatience ces données). Si vous arrêtez de penser aux données sous forme de colonnes différentes dans des tableaux différents, et plus sur votre modèle (plus d'OO), il sera probablement plus facile de travailler avec. Bottom line: Si vous ressentez le besoin de passer des types anonymes, vous êtes probablement en train de faire quelque chose d'autre. –

Répondre

1

Comme personne n'a même tenté de répondre à ma question, je répondrai moi-même ..

Il se trouve, C# 4.0 prend en charge la saisie de canard - ils l'appellent dynamic typing. Cependant, l'utilisation de types dynamiques pour retourner des types anonymes, nous perdons les avantages des types forts:

  • vérification de type Compile temps
  • Performance
  • IntelliSense

J'ai ouvert un demande de fonctionnalité pour avoir des types de retour anonymes fortement typés here - si vous pensez que ce serait un ajout utile à C# 5, suivez le lien et informez l'équipe .Net!

3

Les types anonymes sont principalement conçus pour être utilisés dans une méthode. Ils ne sont pas adaptés à la communication entre les méthodes.

Si vous devez passer un ensemble de données entre deux fonctions de la meilleure façon est de créer un nouveau type d'emballage les données ou utiliser un perdant comme regroupement Tuple<T1,T2> ou KeyValuePair<TKey,TValue>

+0

à l'exception d'un scénario basé sur la réflexion, auquel cas il y a quelques bonnes utilisations (dans le MVC framework html helpers par exemple) –

+0

@Jared: Sauf que avec LINQ, ce n'est pas vrai du tout - LINQ-objects sont certainement destinés à être transmis, mais vous ne pouvez pas le faire en C# en raison des limitations linguistiques. Il * peut * être fait dans VB.net, cependant. –

+0

@BlueRaja, désolé c'est incorrect. Ils ** peuvent ** être transmis dans les deux langues en tant que 'System.Object'. Ils ne peuvent pas être transmis dans les deux langues, car les types anonymes sont bien anonymes. Ils ne peuvent pas être définis directement dans un endroit qui apparaîtrait dans les métadonnées. Dans VB.net (et C# 4.0) vous pouvez contourner ce problème en y accédant d'une manière faiblement typée, mais ce n'est pas ce que le PO demande. – JaredPar

4

Utilisez une couche de modèle de vue. Votre vue doit savoir ce qu'elle va afficher. Je suppose qu'il est possible de créer une vue qui ne fait que formater un tableau multidimensionnel de données, mais ce n'est pas exactement la meilleure raison d'opter pour une solution MVC. Vous pouvez cependant remplir un modèle de vue avec un objet anonyme à consommer dans votre vue.

2

Que pensez-vous de cela? Je suppose que vous avez une classe d'entité pour votre table 'myTable' (appelons-la 'MyTableEntity'), alors pourquoi ne instanciez-vous pas un nouvel objet MyTableEntity et utilisez l'initialiseur d'objet pour remplir uniquement les colonnes que vous voulez?

return (from o in myTable select new MyTableEntity { AColumn = o.column }); 

Cela ne se traduira pas à un SELECT * que vous avez demandé, mais vous aurez toujours un moyen de passer un objet fortement typé à une vue.

Vous devez faire attention à utiliser simplement les propriétés initialisées dans la vue et c'est tout.

Est-ce que cela a du sens pour vous?

+0

C'est une bonne idée - je vais essayer au travail quand j'ai l'occasion (pas pour quelques jours au moins) –

0

Sur .NET 4.0 Les types anonymes peuvent facilement être convertis en ExpandoObjects et ainsi tous les problèmes sont résolus avec le surcoût de la conversion elle-même. Consultez here

0

Vous pouvez facilement convertir les types anonymes en objets dynamiques, voici la mise en oeuvre simple des objets Donymous (objets anonymes dynamiques) qui peuvent peupleront de l'objet Anonymous ou DataReader.

Questions connexes