Linq To EF: Как фильтровать с использованием непримитивных типов

#linq #entity-framework #entity-framework-4 #linq-to-entities

#linq #entity-framework #entity-framework-4 #linq-to-entities

Вопрос:

 public class Person
{
   public int ID { get; set; }
   public int Job { get; set; }
   public string Name { get; set; }
}

List<Person> personsOfInterest = GetPersonsOfInterest();

PersonEntities personEntities = new PersonEntities();

var filteredPersons = personEntities.Where(p => personsOfInterest.Any(poi => poi.Job == p.Job amp;amp; poi.Name == p.Name));
  

Приведенный выше код генерирует исключение NotSupportedException, поскольку Linq to Entities не поддерживает ссылки на нескалярные переменные ( Person ).

как я могу это решить? Спасибо!

// редактировать: Я пытаюсь найти людей из personEntities, у которых одинаковое имя и одинаковая работа с кем-либо в списке personOfInterest. например, я пытаюсь найти кого-либо из моих знакомых, кто является полицейским по имени Боб или программистом по имени Джон.
ошибка, которую я получаю, описана в here.(22.2)

Комментарии:

1. что именно представляет собой сообщение об исключении? это часть о том, что «Linq к сущностям не поддерживает ссылки на нескалярные переменные (Person). » из сообщения » это ваш анализ?» потому что я считаю, что это из-за «poi.Job == p.Job».

2. Не похоже, что ваш код будет компилироваться. Contains принимает Person объект в качестве первого параметра, а не лямбда-выражение. Вместо этого вы должны использовать Any .

3. Не могли бы вы описать словами, что именно у вас есть и пытаетесь сделать?

4. Я добавил свой ответ. Хотя у меня все еще есть вопрос: PersonEntities в вашем коде, это пользовательский тип коллекции или это табличный / комплексный тип в вашей модели EF?

5. это табличный / сложный тип в моей модели EF

Ответ №1:

Прежде всего, обе коллекции должны содержать объекты одного и того же типа.

Затем вы могли бы сделать следующее:

     var filteredPerosns = personEntities
          .Where(p => personsOfInterest.Contains(p, new MyPersonComparer()));
  

создайте класс:

     class MyPersonComparer : IEqualityComparer<Person>
    {
        public bool Equals(Person x, Person y)
        {
            return x.Job == y.Job amp;amp; x.Name == y.Name; 
        }

        public int GetHashCode(Person obj)
        {
            return obj.PersonID; //Just for example...
        }
    }
  

ИЛИ, если первое не подходит, вы могли бы объединить что-то в соответствии с концепцией:

     List<int?> listA = new List<int?>() {1, 2, 3, 4, 5, 6, 7};
    List<int?> listB = new List<int?>() {5};

    bool result = (from a in listA
                   join b in listB on a equals b 
                   select a).Any();
  

Я не знаю внутренностей ваших классов, поэтому вам придется скорректировать примеры в соответствии с вашей структурой объекта.

ОТРЕДАКТИРОВАНО: Я изменил приведенный выше пример, чтобы отразить отредактированное вами описание:

     List<Person> personsOfInterest = GetPersonsOfInterest();

    var filteredPersons = (from a in personEntities
           join b in personsOfInterest on new{a.Name, a.Job} equals new {b.Name, b.Job} 
           select a).ToList();
  

PersonEntities в вашем коде, это пользовательский тип коллекции или это табличный / комплексный тип в вашей модели EF?

Ответ №2:

Лучше всего было бы сравнивать идентификаторы, а не объекты. Это будет намного эффективнее. Проблема в том, что EntityFramework не знает, как перевести obj1 == obj2 в SQL.

Комментарии:

1. Я не могу сравнивать с IDS — два человека с разными ID могут иметь одинаковые имена и одинаковые задания.