2008-12-10 8 views
2

J'ai déclaration LINQ qui ressemble à ceci:Encapsulation LINQ instruction select

return (from c in customers select new ClientEntity() { Name = c.Name, ... }); 

Je voudrais pouvoir faire abstraction la sélection dans sa propre méthode pour que je puisse avoir différentes options « mapping ». Qu'est-ce que ma méthode doit retourner?

Essentiellement, je voudrais ma requête LINQ pour ressembler à ceci:

return (from c in customers select new Mapper(c)); 

Edit:

Ceci est pour LINQ to SQL.

Répondre

4

Nouvelle réponse maintenant, je l'ai remarqué que c'est LINQ to SQL ... :)

Si vous regardez la version de Select qui fonctionne sur IQueryable<T> il ne prend pas Func<In, Out>. Au lieu de cela, il faut un Expression<Func<In, Out>>. Le compilateur sait comment générer une telle chose à partir d'un lambda, c'est pourquoi votre code normal compile.

donc d'avoir une variété de fonctions de mappage de sélection prêtes à l'emploi en les faisant passer pour sélectionner, vous pouvez les déclarer comme ceci:

private static readonly Expression<Func<CustomerInfo, string>> GetName = c => c.Name; 

private static readonly Expression<Func<CustomerInfo, ClientEntity>> GetEntity = c => new ClientEntity { Name = c.Name, ... }; 

Vous pouvez ensuite les utiliser comme ceci:

var names = customers.Select(GetName); 

var entities = customers.Select(GetEntity); 
+0

Après avoir écrasé à la fois votre solution et bdukes, je dois dire que votre solution est meilleure car elle est capable d'analyser l'expression et d'en construire du SQL. bdukes a apporté tous les résultats, puis appliqué d'autres clauses en mémoire. –

0

Ceci est pour Linq aux objets? Ou pour un linq? Parce que ... sélectionnez un nouveau mappeur (c), nécessite que 'c' soit déjà matérialisé dans un objet, puis passé à Mapper() CTor. (comme 'c' n'est pas connu au niveau de la base de données, seulement au niveau .NET)

1

Vous devrez peut-être utiliser des méthodes chaînées au lieu d'utiliser la syntaxe LINQ, et vous pourrez ensuite passer un des variété de Expression<Func<TSource, TResult>> valeurs que vous spécifiez:

Expression<Func<CustomerTable, Customer>> someMappingExpression = c => new Customer { Name = c.Name }; 
return context.CustomerTable.Select(someMappingExpression); 

MISE à JOUR: Select prend un Func, pas un Expression
MISE à JOUR: La fonction Select qui doit être utilisée prend un Expression<Func>, plutôt qu'un simple Func.

+0

L'exemple de code dans cet exemple est une erreur de syntaxe, est-ce pas? De plus, le commentaire "Select prend un FUnc, pas une Expression" est incorrect pour Linq to SQL. –

+0

C'est mieux! :) –

0

BTW: Les solutions décrites ici ne fonctionneront que si vous voulez utiliser la partie 'factorisée' du code dans une clause de requête séparée (par exemple, Select). Si vous souhaitez l'utiliser en tant que partie d'une clause qui fait également quelque chose (peut-être retourner le type anonyme avec d'autres informations), vous devrez construire l'arborescence entière dynamiquement en utilisant Expression.Xyz méthodes.

Sinon, vous pouvez utiliser l'astuce pour intégrer des expressions lambda que je viens de décrire ici:

Questions connexes