Établissez un lien entre deux listes de linq vers des entités où clause

Je suis assez nouveau pour Linq et EF et je ne comprends pas comment je pourrais relier deux listes de Linq à des entités.

J’utilise Database First et j’ai deux tables:

Person , avec Id colonne
et
Ability , avec les colonnes Id , PersonId et Value

Ainsi, la classe Person a une ICollection , appelée AllAbilities .

Dans le ViewModel de certaines vues, je récupère une liste d’int, représentant les valeurs des Ability.Value de Ability.Value entrées par l’utilisateur pour Ability.Value , appelé AbilitiesInput . Mon besoin est simple, dans le contrôleur je dois appeler une requête qui ferait ce qui suit:

 GetAll(person => for(i = 0; i  AbilitiesInput[i] } ) 

Où la méthode GetAll ressemble à cela dans mon GetAll générique:

 public virtual async Task<List> GetAll( Expression<Func> wherePredicate = null { ... } 

Pour résumer, j’ai juste besoin d’un booléen qui puisse vérifier si chaque AllAbilities[i] est supérieur à AbilitiesInput[i] , mais rien de ce que j’ai essayé n’a fonctionné.
J’ai essayé de modifier AbilitiesInput to List ou List mais une erreur s’est List No mapping exists , j’ai essayé d’utiliser un FindIndex Select pour créer un nouvel object, FindIndex également essayé d’utiliser IndexOf ou FindIndex pour obtenir un index sans foreach .. .

Si quelqu’un pouvait m’expliquer comment je pouvais réaliser cette chose simple, je serais si heureux.
Merci beaucoup.

Je suis assez nouveau pour Linq et EF

Vous n’avez pas de chance, car “cette chose simple” est relativement facile dans LINQ to Objects, mais assez difficile (voire impossible) dans LINQ to Entities.

Pour le résoudre, vous devez créer manuellement une Expression compatible LINQ to Entities.

Premièrement, vous aurez besoin d’aides pour la construction de prédicats d’expression. PredicateBuilder est un choix LinqKit , mais il ne produit pas d’expressions compatibles EF et requirejs LinqKit et AsExpandable à l’intérieur du référentiel. J’utilise donc les aides ci-dessous qui sont similaires, mais produisent des expressions compatibles finales:

 public static class PredicateUtils { sealed class Predicate { public static readonly Expression> True = item => true; public static readonly Expression> False = item => false; } public static Expression> Null() { return null; } public static Expression> True() { return Predicate.True; } public static Expression> False() { return Predicate.False; } public static Expression> And(this Expression> left, Expression> right) { if (Equals(left, right)) return left; if (left == null || Equals(left, True())) return right; if (right == null || Equals(right, True())) return left; if (Equals(left, False()) || Equals(right, False())) return False(); var body = Expression.AndAlso(left.Body, right.Body.Replace(right.Parameters[0], left.Parameters[0])); return Expression.Lambda>(body, left.Parameters); } public static Expression> Or(this Expression> left, Expression> right) { if (Equals(left, right)) return left; if (left == null || Equals(left, False())) return right; if (right == null || Equals(right, False())) return left; if (Equals(left, True()) || Equals(right, True())) return True(); var body = Expression.OrElse(left.Body, right.Body.Replace(right.Parameters[0], left.Parameters[0])); return Expression.Lambda>(body, left.Parameters); } static Expression Replace(this Expression expression, Expression source, Expression target) { return new ExpressionReplacer { Source = source, Target = target }.Visit(expression); } class ExpressionReplacer : ExpressionVisitor { public Expression Source; public Expression Target; public override Expression Visit(Expression node) { return node == Source ? Target : base.Visit(node); } } } 

Deuxièmement, définissez une méthode d’assistance dans votre contrôleur pour un critère unique comme celui-ci.

 static Expression> AbilityFilter(int index, int value) { return p => p.AllAbilities.OrderBy(a => a.Id).Skip(index).Take(1).Any(a => a.Value > value); } 

Enfin, construisez le filtre et transmettez-le à la méthode GetAll :

 var filter = PredicateUtils.Null(); for (int i = 0; i < AbilitiesInput.Count; i++) filter = filter.And(AbilityFilter(i, AbilitiesInput[i])); GetAll(filter); 

Les techniques utilisées ne sont certainement pas pour un novice, mais je ne vois pas de moyen simple de résoudre ce problème particulier.

Je ne sais pas si j’ai bien compris, mais le code ci-dessous peut aider à trouver la solution correcte Utiliser (x, i) énumérera la collection et obtiendra un index afin que vous puissiez comparer les deux collections.

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { List AbilitiesInput = null; public Form1() { InitializeComponent(); AbilitiesInput = new List() { textBox1, textBox2, textBox3, textBox4 }; Person person = new Person(); List results = person.AllAbilities.Where((x, i) => x.Value > int.Parse(AbilitiesInput[i].Text)).ToList(); } } public class Person { public int Id { get; set; } public List AllAbilities { get; set; } public Person() { AllAbilities = new List(); } } public class Ability { public int Id { get; set;} public int PersonId { get; set; } public int Value { get; set; } } }