2010-09-05 3 views
5

Je suis en train de résoudre un problème similaire à celui décrit iciEviter le code de projection répétée dans Entity Framework

Initializing strongly typed objects in LINQ to Entities

seulement de totalement le sens opposé. J'ai un certain nombre de fonctions dans mon dépôt, qui retournent toutes des données de forme identique. La question est mon code de projection:

select new pocoClass 
{ 
    // complex projection that is several pages long includes grabbing a graph of data 
} 

au moment où il existe pour chaque requête dans le référentiel. J'avais essayé de le déplacer dans un initialiseur d'objet, mais cela me donne le redouté "Seuls les constructeurs et les initialiseurs sans paramètre sont supportés dans LINQ to Entities." problème.

J'ai essayé diviser en deux requêtes

var candidates = (from thing in _entities.whatever 
    where (complex.stuff==true) 
    select thing); 

var final = (from thing in candidates.AsEnumerable() 
    let x = thing.ITEMS.Where(blah=>blah.blah==param) 
    let y = x.OTHERITEMS.FirstOrDefault() 
    select new pocoClass(thing,x,y); 

mais ici final est toujours nul et le code dans la nouvelle pocoClass est jamais appelé. J'ai inclus le let x & y dans le tableau ci-dessus parce que ceux-ci varient toujours entre chaque utilisation de la projection. Donc, dois-je revenir à plusieurs copies de ma projection ou y a-t-il un autre moyen de s'en sortir?

Répondre

12

Je ne suis pas sûr qu'il est ce utile pour vous, mais ce que je fais souvent est de créer des méthodes de projection qui prennent un IQueryable et retourner un IQueryable à traduire à partir d'un objet de domaine à un DTO. Ils ressemblent beaucoup à ceci:

public static IQueryable<CustomerDTO> ToCustomerDTO(
    IQueryable<Customer> customers) 
{ 
    return 
     from customer in customers 
     select new CustomerDTO() 
     { 
      ... 
     }; 
} 

Cela me permet d'avoir cette projection dans un seul endroit. De plusieurs endroits dans ma couche de gestion j'appelle une telle méthode.

Il y a quelques choses à noter, cependant:

  • Assurez-vous que ces méthodes de projection ne contiennent pas de logique métier. Avoir des filtres spécifiques au cas d'utilisation serait mauvais.
  • Parfois, vous avez un DTO qui contient un graphe d'objet complexe que vous voulez extraire efficacement de la base de données dans une seule requête. Avec un peu de créativité, c'est très souvent possible, mais pas lors du retour d'un IQueryable. Dans ce cas, je renvoie un tableau de DTO.
  • Je place ces méthodes de projection comme méthodes statiques à l'intérieur de la classe DTO. Bien que ce ne soit pas un design très propre, il a découvert qu'il rend le code très facile à maintenir.

J'espère que cela aide.

+0

Presque - c'est le problème de la logique applicative - dans mon exemple les instructions let qui sont évaluées pour chaque client avant la projection. – Andiih

+0

En fait, c'est assez pour me donner une solution. J'ai créé une nouvelle classe intermédiaire DTO simplifiée que je peux projeter en copiant une demi-douzaine de valeurs: chacune étant une entité EF entière. Ensuite, j'utilise votre solution pour faire la projection finale de ces entités. Je ne sais pas comment cela va fonctionner, mais c'est certainement plus propre! – Andiih

+0

@Andiih: Vous devrez utiliser le profileur SQL pour voir combien de requêtes sont exécutées en arrière-plan. Il y a un bon changement qu'EF exécutera de nombreuses requêtes derrière les couvertures. La technologie a bien sûr ses limites. Si vous n'êtes pas satisfait de la performance et que vous n'avez aucune idée de comment l'obtenir dans une seule requête, peut-être que je peux vous aider avec cela. Dans ce cas, lancez une nouvelle question ici à SO et déposez un lien ici.À votre santé – Steven

Questions connexes