Почему я получаю ошибку времени компиляции в этом запросе LINQ?

StackOverflow https://stackoverflow.com/questions/20354027

  •  25-08-2022
  •  | 
  •  

Вопрос

Я получаю ошибку времени компиляции при составлении приведенного ниже кода, и я не понимаю, почему:

Отношения много ко многим отношениям

 var contacts = groups_to_querry
                .SelectMany(x => x.Contacts)
                .Where(x => x.ID == Guid.Empty)
                .SelectMany(p => p.ContactDetails)
                .Where(x => x.ID == Guid.Empty)
                .SelectMany(x => x.Contacts);  //This line gives me a compile time error 
                //Error : The Type argumetns for method 'System.Linq.Enumerable.SelectMany<TSource,Tresult>
                //(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,
                //System.Collections.Generic.IEnumerable<TResult>>)' cannot be infrred from the usage.  
                //Try specifying the type arguments explicitly
Это было полезно?

Решение

Во второй раз, когда вы звоните .SelectMany(x => x.Contacts), в настоящее время вы работаете с коллекцией ContactDetails. Анкет Сомнительно, что вы сможете использовать SelectMany в теме. Вам нужно использовать Select вместо.

SelectMany используется, когда вы хотите выбрать несколько коллекций элементов и положить их в один IEnumerable. Select используется на отдельных полях. Поскольку вы работаете с объектами типа ContactDetail (что, я полагаю, может иметь только один контакт), вам нужно использовать Select

Изменить: вот что вы делаете в двух словах, шаг за шагом:

groups_to_querry.SelectMany(x => x.Contacts): Из всех групп, которые я хочу запросить, выберите все их многочисленные контакты. У каждой группы много контактов, поэтому поместите их все в один IEnumerable Коллекция типа Contact

.Where(x => x.ID == Guid.Empty): ... но только эти контакты с пустым идентификатором

.SelectMany(p => p.ContactDetails): Затем выберите все эти контакты много контактов. Каждый контакт имеет много контактов, поэтому поместите их все в один IEnumerable Коллекция типа ContactDetail

.Where(x => x.ID == Guid.Empty): ... но только те контакты с пустым идентификатором

.SelectMany(x => x.Contacts);: Теперь выберите каждый из контактов ContactDetails. Однако, поскольку компилятор знает, что между контактами и контактами (а не наоборот) существует связь между контактами и контактами (а не наоборот), и, следовательно, показывает ошибку компиляции

Другие советы

Я интерпретирую ваш предполагаемый запрос как «из нескольких групп контактов, выберите все контакты, которые имеют id = guid.empty, а также есть подробности, которые имеют идентификатор = guid.empty».

То, как ваш код фактически интерпретируется, «из всех контактов, которые имеют guid.empty, выберите все данные, которые имеют guide.empty, и из этих данных выберите все контакты». Первая проблема в том, что вы в конечном итоге выбираете из деталей. Это означает финал SelectMany должен быть Select, потому что x.Contacts Здесь относится к отношению к многим к одному от деталей до контактов.

Вторая проблема заключается в том, что результат будет содержать дубликаты контактов, поскольку для каждой детали включен один и тот же контакт. Вместо этого вы должны делать фильтрацию контактов непосредственно на основе их коллекций данных, например, это:

groups_to_query
.SelectMany(g => g.Contacts)
.Where(c => c.ID == Guid.Empty)
.Where(c => c.ContactDetails.All(d => d.ID == Guid.Empty))

Обратите внимание, что это также выберет контакты, которые имеют нулевые детали, что отличается от поведения от вашего запроса, поэтому я не уверен, что это то, что вы хотите. Вы можете добавить еще один фильтр для ContactDetails.Any() если не.

Редактировать: Поскольку вы используете структуру сущности, вышеупомянутое, вероятно, не сработает. Вам может потребоваться выбрать детали в подпроводе, а затем фильтровать в памяти после того, как он выполняется:

var queryResult =
    groups_to_query
    .SelectMany(g => g.Contacts)
    .Where(c => c.ID == Guid.Empty)
    .Select(c => new {
        contact = c,
        detailIDs = c.ContactDetails.Select(d => d.ID)
    }).ToList();

var contacts =
    queryResult
    .Where(r => r.detailIDs.All(id => id == Guid.Empty))
    .Select(r => r.contact);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top