Estabelecer um link entre duas listas no linq para entidades onde cláusula

Eu sou muito novo no Linq e EF e estou preso em relação a como eu poderia apenas ligar duas listas no Linq to Entities.

Estou usando o Database First e tenho duas tabelas:

Person , com Id colunas
e
Ability , com colunas Id , PersonId e Value

Assim, a class Person possui um ICollection , chamado AllAbilities .

No ViewModel de alguma View, recebo de volta uma lista de int, representando valores de checkboxs de texto inseridos pelo usuário para Ability.Value , chamado AbilitiesInput . Minha necessidade é simples, no Controller eu tenho que chamar uma consulta que faria o seguinte:

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

Onde o método GetAll parece com isso no meu repository genérico:

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

Para continuar, eu só preciso de um booleano que possa verificar se todas as AllAbilities[i] são superiores a AbilitiesInput[i] , mas nada que eu tentei funcionou.
Tentei alterar AbilitiesInput para List ou List mas recebi um erro dizendo que No mapping exists , tentei usar um Select para criar um novo object, também tentei usar IndexOf ou FindIndex para obter o índice sem foreach .. .

Se alguém pudesse me explicar como eu posso conseguir essa coisa simples, eu ficaria tão feliz.
Muito obrigado.

    Eu sou muito novo para Linq e EF

    Você está sem sorte, porque “essa coisa simples” é relativamente fácil no LINQ to Objects, mas bastante difícil (quase impossível) no LINQ to Entities.

    A fim de resolvê-lo de alguma forma, você precisa construir manualmente Expression compatível com LINQ to Entities.

    Primeiro, você precisará de alguns ajudantes para construir predicados de expressão. O PredicateBuilder é uma escolha popular, mas não produz expressões compatíveis com o EF e requer o LinqKit e o AsExpandable dentro do repository. Então eu uso os helpers abaixo que são semelhantes, mas produzem expressões compatíveis finais:

     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); } } } 

    Segundo, defina um método auxiliar em seu controlador para um único critério como este

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

    Finalmente, construa o filtro e passe-o para o método GetAll :

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

    As técnicas utilizadas definitivamente não são para um novato, mas não vejo uma maneira simples de resolver esse problema específico.

    Não tenho certeza se acertei, mas o código abaixo pode ajudar a obter a solução correta. Usando (x, i) irá enumerar através da coleção e obter um índice para que você possa comparar as duas 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; } } }