2010-12-10 28 views
1

Je souhaite créer un objet Entity à partir d'une instruction LinQ, mais je ne souhaite pas charger toutes ses colonnes.Entity Framework - Problème de projection LinQ

Mon objet ORDERS contient beaucoup de colonnes, mais je veux juste récupérer les colonnes REFERENCE et OPERATION pour que l'instruction SQL et le résultat soient plus petits.

Cette déclaration LinQ fonctionne correctement et charges tous mes attributs d'objet:

var orders = (from order in context.ORDERS 
      select order); 

Cependant, la déclaration suivante ne se charge que deux propriétés de mon objet

var orders = (from order in context.ORDERS 
       select new ORDERS 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION 
       }); 

L'erreur renvoyée est:

The entity or complex type 'ModelContextName.ORDERS' cannot be constructed in a LINQ to Entities query.

Quel est le problème? N'est-il pas possible de charger partiellement un objet de cette façon?

Merci d'avance pour vos réponses.


RÉPONSE

Ok je vous remercie tous les deux Yakimych et Dean parce que je l'utilise à la fois de vos réponses, et maintenant j'ai:

var orders = (from order in context.ORDERS 
       select new 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION, 
       }) 
       .AsEnumerable() 
       .Select(o => 
         (ORDERS)new ORDERS 
         { 
          REFERENCE = o.REFERENCE, 
          OPERATION = o.OPERATION 
         } 
     ).ToList().AsQueryable(); 

Et je reçois exactement ce que je veux, le SQL Statement n'est pas parfait mais il retourne seulement les 2 colonnes dont j'ai besoin (et une autre colonne qui contient pour chaque ligne "1" mais je ne sais pas pourquoi pour l'instant) - J'ai aussi essayé de construire des sous-objets avec cette méthode Ça marche bien.

Répondre

2

Non, vous ne pouvez pas projeter sur un objet mappé. Vous pouvez utiliser un type anonyme à la place:

var orders = (from order in context.ORDERS 
       select new 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION 
       }); 
+0

OK, j'ai déjà essayé mais comment puis-je convertir cet objet anonyme en type Entity? – mbp

+2

Vous ne pouvez pas mapper cela à une entité.Vous pouvez créer un objet personnalisé (DTO) pour cela, mais vous ne pouvez pas charger partiellement une entité, car EF ne saurait pas en faire quoi que ce soit lorsque vous essayez de le modifier et de le sécuriser. – Steven

0

Je pense que la question est de créer de nouvelles entités au sein de la requête elle-même, alors que diriez-vous d'essayer ceci:

context.ORDERS.ToList().Select(o => new ORDERS 
{ 
    REFERENCE = o.REFERENCE, 
    OPERATION = o.OPERATION 
}); 
+0

Cela ne résoudra pas le problème avec la requête SQL. Ce sera comme si vous récupériez tout l'objet et que vous récupériez des données de tous les champs. Après cela est exécuté, vous transformez les résultats en mémoire. Cependant, il n'y a vraiment aucun intérêt à le faire par la suite. – Yakimych

+0

S'il vous plaît vérifier mon premier message parce que je ne peux pas poster le code source ici. – mbp

2

Le problème avec la solution ci-dessus est que de Au moment où vous appelez AsEnumerable(), la requête sera exécutée sur la base de données. Dans la plupart des cas, tout ira bien. Mais si vous travaillez avec une grande base de données, l'extraction de toute la table (ou vue) n'est probablement pas ce que vous voulez. Donc, si on enlève le AsEnumerable, nous sommes de retour à la case 1 avec l'erreur suivante:

The entity or complex type 'ModelContextName.ORDERS' cannot be constructed in a LINQ to Entities query.

Je me bats avec ce problème pour une journée entière et est ici ce que j'ai trouvé. J'ai créé une classe vide héritant de ma classe d'entité et effectué la projection en utilisant cette classe.

public sealed class ProjectedORDERS : ORDERS {} 

La requête projetée (en utilisant la fonction de covariance):

IQueryable<ORDERS> orders = (from order in context.ORDERS 
       select new ProjectedORDERS 
       { 
        REFERENCE = order.REFERENCE, 
        OPERATION = order.OPERATION, 
       }); 

Voilà! Vous avez maintenant une requête projetée qui sera mappée à une entité et qui ne sera exécutée que lorsque vous le souhaitez.

+0

+1 Moi aussi, j'ai passé beaucoup de temps sur ce problème et, après mille tentatives infructueuses, je suis arrivé à la même solution que vous; classe vide héritant de l'entité et être fait avec elle. Pourtant, j'aimerais savoir pourquoi EF ne permet pas de projeter vers des classes d'entités, car cela serait incroyablement pratique dans beaucoup de circonstances :( –