0

J'ai jeté ce code parce que cela a fonctionné, mais j'ai vraiment besoin de refactoriser quelque chose d'acceptable. Il accepte un ensemble d'objets de requête (chaînes ressemblant à productid = 3) puis les ajoute à ma requête. Cela ne fonctionne que pour AND logique, mais j'aurai éventuellement besoin de quelques opérateurs logiques différents (OR, NOT).Entity Framework 4 et Linq to Entities spécifications: Comment le coder?

-- Idea here is add the where clause to the original query and return a new one 
private static IQueryable<Product> GetFilteredQuery(string condition, 
    IQueryable<Product> originalQuery) 
    { 
     -- REPETITION 
     if(-- Regex comparison looking for "productid = 123" --) 
     { 
      returnQuery = originalQuery.Where(
        p => p.myEntity.SelectMany(q => q.subEntity) // spec expression 
          .Any(r => r.id == foundid));   
     } 
     ... (one if statement for each specification, calling this several times) 

J'ai aussi ce pour la commande:

private static IQueryable<Product> GetOrderedQuery(IList<string> fields, 
    IQueryable<Product> originalQuery) 
{ 
    var resultQuery = originalQuery; 
    bool firstTime = true; 
    foreach(var field in fields) 
    { 
     -- REPETITION 
     if(field == "id") 
     { if(firstTime == true) 
      { resultQuery = resultQuery.OrderBy(p => p.id); 
       firstTime = false; 
      } 
      else 
      { resultQuery = resultQuery.ThenBy(p => p.id); 
      } 
     } 
     ... (one for each field to order by) 
    } 

Alors, comment pourrais-je résumer chaque répétition pour un objet de spécification où je peux en quelque sorte joindre cette collection de spécifications à ma requête d'origine, y compris l'ordre expressions? C'est sous Linq to Entities, Entity Framework 4 et parapluie C#.

Ce serait vraiment bien de faire quelque chose comme ça, ce qui est essentiellement ce qui précède.

var originalQuery = ...; 
foreach(var spec in mySpecs) 
{ originalQuery = spec(originalQuery); //adds all the where clauses 
} 

originalQuery = orderSpec(originalQuery); // adds all the order fields 

Des liens vers des sites Web, exemple de code, seraient certainement appréciés.

+0

Suis-je le seul qui manque ici le point derrière ces méthodes? Ne serait-il pas plus facile d'autoriser l'appelant à enchaîner les appels LINQ eux-mêmes plutôt que d'essayer de sur-manipuler quelque chose pour le cacher? –

+0

Les champs proviennent du client. Le client est un navigateur Web envoyant JSON d'avant en arrière. Je devrai passer en revue chaque fourni par le client et l'implémenter. –

+0

Qu'en est-il de la désérialisation de l'objet JSON en .NET (appelons cela les conditions de recherche), puis de la construction de Linq en entités pour une structure de conditions de recherche bien connue? –

Répondre

1

La seule chose que j'ai vu quelque chose de semblable était le suivant:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Mais ce n'est pas spécifique à EF 4. Pourquoi ne pas convertir la requête SQL entité?

Vous pouvez créer la requête comme une chaîne, et ajouter ces termes à cette requête SQL.

HTH.

+0

Seul problème avec SQL dynamique est il n'est pas fortement typé. Le modèle de Spécification serait fortement typé, en utilisant des expressions Lambda pour indiquer la participation. p => p.name –

+0

Avec Dynamic SQL, je suis d'accord, vous pouvez utiliser la fonction Cast pour convertir le type approprié. Entité SQL fonctionnerait. –

1

Jetez un oeil à LinqSpecs, il pourrait faire ce que vous avez besoin, ou au moins vous donner quelques idées pour travailler avec.

D'après ce que je comprends, vous pourriez être en mesure de faire quelque chose comme:

var originalSpec = ...; 
var composedSpec = originalSpec; 

foreach(var spec in mySpecs) 
{  
    composedSpec &&= spec; //adds all the where clauses 
} 

composedSpec &&= orderSpec; // adds all the order fields