Comment créer une expression avec une autre expression en C #?

J'essaie d'écrire des requêtes Linq sur SQL et autres et j'ai trouvé que je devais utiliser des expressions au lieu de lambdas.

Si vous ne le faites pas, il essaie de convertir votre Linq directement en SQL et cela ne fonctionne pas.

Prenez un exemple de keys primaires sur une table. Les nôtres ont tous un nom différent, mais j'aimerais écrire une clause Linq WHERE standard qui utilise une expression pour choisir le bon champ.

J'ai écrit le code de test suivant:

static void Main(ssortingng[] args) { using (var ss = new DataScope() { var db = DataScope.DatabaseConnection; var pk = 2; var sql = db.Beats.AsQueryable(); sql = sql.Where(Filter(pk)); var res = sql.ToList(); } } static Expression<Func<Beat, bool>> Filter(int pk) { return e => e.BeatID > pk; } 

Le code est Main works, Filter (int) filters par PKID et je peux le convertir en code générique, avec plus de propriétés dérivées returnnant l'expression sur une base par table.

Mais c'est un peu limité, j'aimerais plutôt seulement définir l'expression pointant vers le champ PK et en build d'autres expressions.

Sinon, si je veux PKGreaterThan et PKEquals, je dois le définir deux fois pour chaque table. Et j'ai besoin d'une douzaine, et il y a des centaines de tables.

Il serait beaucoup plus facile de faire en sorte que chaque table définisse des expressions pointant vers des champs keys (PK, GUID, string unique, date de création, etc.)

Mais je ne sais pas comment.

Jusqu'à présent, le meilleur que j'ai trouvé (et ça ne marche pas du tout) est:

  static Expression<Func<Beat, int>> PKExpression { get { return e => e.BeatID; } } static Expression<Func<Beat, bool>> SuperFilter(int pk) { var gt = Expression.GreaterThan(PKExpression, Expression.Constant(pk)); return e => gt; } 

Comment j'enveloppe Expression.GreaterThan dans Expression<Func<Beat, int>>

Je pense que vous devez convertir cela en expression lambda par Expression.Lambda<Func<Beat, bool>>

 ParameterExpression param = Expression.Parameter(typeof(Beat)); var gt = Expression.GreaterThan(Expression.Call(PKExpression,param), Expression.Constant(pk)); LambdaExpression condition =Expression.Lambda<Func<Beat, bool>>(gt, param); return condition; 

Debout sur les épaules de Mehdi, j'ai réussi à find ce qui suit:

 class Program { static void Main(ssortingng[] args) { using (var ss = new DataScope(@"connSsortingng")) { var db = DataScope.DatabaseConnection; var pk = 2; var sql = db.Beats.AsQueryable(); sql = sql.Where(PKGreaterThan(pk)); var res = sql.ToList(); } } static ssortingng PKName { get { return "BeatID"; } } static PropertyInfo PKProperty() { var output = typeof(Beat).GetProperties().Where(p => p.Name == PKName).SingleOrDefault(); return output; } static Expression<Func<Beat, bool>> PKGreaterThan(int pk) { var beatParameter = Expression.Parameter(typeof(Beat)); var beatPKProperty = Expression.Property(beatParameter, PKProperty()); var beatPKGreaterThanPK = Expression.GreaterThan(beatPKProperty, Expression.Constant(pk)); var output = Expression.Lambda<Func<Beat, bool>>(beatPKGreaterThanPK, beatParameter); return output; } } 

Il est maintenant dans une class de base générique avec le type T étant la class linq to sql row. Tout ce que vous avez à faire maintenant est de surcharger la propriété PKName et toutes les expressions PK fonctionnent avec les clauses et les jointures SELECT generics.