2010-12-14 72 views
0

Comment puis-je itérer une expression LINQ et le convertir en paramètre DB afin que je puisse éviter de passer paramètres multiples en entrée à la méthode DALitérer une expression LINQ et le convertir en paramètre DB

couche d'affaires: en BL j'ai le code comme ceci

database.GetProduct(a => a.ProductType == "tea" || a.Price <= 5); 

en DAL j'utilise ADO.Net plaine et que vous souhaitez convertir l'expression tout ce que je suis revenu de BL à ADO.Net paramètres

d'accès aux données couche:

public DataSet GetProduct(Expression<Func<Product, bool>> pred) 
{ 

    step 1: 
      Iterate the predicate and create new sqlparameter. 
    step 2: 
     return database.ExecuteDataset(parameters)  
} 

Comment puis-je itérer « pred » & convertir en SqlParameter

+3

Linq fournisseur fait cela, pourquoi devez-vous le répéter? – Aliostad

+0

Parce que je n'utilise pas Linq 2 sql/Entity Framework/N Hibernate, j'utilise ADO.Net simple – kayak

+0

^Il n'utilise pas de fournisseur Linq, il utilise vanilla ADO.NET –

Répondre

1

Comme l'écrit Matthew, vous aurez besoin de traiter l'arbre d'expression. Cela peut être fait en utilisant ExpressionVisitor, ce qui vous permet d'écrire du code pour chaque type de nœud dans l'arbre d'expression. Toutefois, si vous ne voulez prendre en charge que des expressions simples (telles que celle de votre exemple), vous pouvez utiliser la propriété NodeType pour le traiter.

La structure pourrait être quelque chose comme:

static void HandlePrimitive(Expression e) { 
    // TODO: Handle primitive cases (>, <, <=, !=, >=, ..) 
    Console.WriteLine(e.NodeType); 
} 

static void Process(Expression e) { 
    if (e.NodeType == ExpressionType.OrElse) 
    { 
    // Process left subexpression (one (in)equality) as primitive 
    // and right subexpression recursively (it may be either primitive 
    // or another OrElse node. 
    var be = e as BinaryExpression; 
    HandlePrimitive(be.Left); 
    Process(be.Right); 
    } 
    else HandlePrimitive(e); 
} 

Expression<Func<Product,bool>> f = a => a.ProductType == "tea" || a.Price <= 5; 
Process(f.Body); 

La méthode Process récursive itère sur toutes les sous-expressions composées en utilisant l'opérateur « ou » (vous pouvez soutenir « et » De la même façon). La méthode HandlePrimitive traiterait des expressions qui peuvent être composées en utilisant ||'s. These are other BinaryExpression values (e.g. Equal or LessThanEqual ). You'll need to look at their Left and Right Propriété permettant de connaître le nom et la valeur de la propriété comparée à celle de la propriété .. type d'expressions.

1

Vous devez regarder dans le modèle des visiteurs sur votre expression de sorte que vous pouvez marcher à travers l'arbre d'expression vous générer pour déterminer les membres à projeter en tant que paramètres. Le projet IQToolkit a une belle classe de base ExpressionVisitor que vous pourriez trouver utile en tant qu'implémentation de base du modèle de visiteur. Vous pourriez sous-classer cela pour gérer le VisitMemberAccess spécifiquement pour traiter vos propriétés.

+0

Merci, je vais vérifier celui-là – kayak

+0

Juste un commentaire; la classe ExpressionVisitor est intégrée dans .NET 4. – KeithS

-1

Vous ne voulez pas descendre cette route. Vous allez réimplémenter LINQ en SQL. Je pourrais suggérer que vous utilisiez des arguments optionnels:

public DataSet GetProduct(int? maxPrice = null, string type = null) 
{ 
    //... snip ... 
    if (price.HasValue) whereClause += " OR price <= " + maxPrice"; 
    //... snip ... 
} 
+0

Si les expressions Linq s'avèrent difficiles, je vais finir par faire comme ça – kayak

+0

@kayak, ce ne sera probablement pas trop difficile de faire fonctionner les cas simples, mais honnêtement, vous le ferez beaucoup de travail pour réimplémenter quelque chose que Microsoft offre gratuitement. – tster