Pergunta

Estou recebendo um erro de tempo de compilação ao compilar o código abaixo e não consigo ver o porquê:

As relações são muitas para muitas relações

 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
Foi útil?

Solução

A segunda vez que você chama .SelectMany(x => x.Contacts), você está trabalhando com uma coleção de ContactDetails. É duvidoso que você possa usar SelectMany nele. Você precisaria usar Select em vez de.

SelectMany é usado quando você deseja selecionar várias coleções de itens e colocá -los em um IEnumerable. Select é usado em campos individuais. Já que você está trabalhando com objetos do tipo ContactDetail (que eu presumo só pode ter um contato), você precisaria de uso Select

EDIT: Aqui está o que você está fazendo em poucas palavras, passo a passo:

groups_to_querry.SelectMany(x => x.Contacts): De todos os grupos que quero consultar, selecione todos os seus muitos contatos. Cada grupo tem muitos contatos, então coloque -os em um único IEnumerable coleção de tipo Contact

.Where(x => x.ID == Guid.Empty): ... mas apenas aqueles contatos com um ID vazio

.SelectMany(p => p.ContactDetails): Em seguida, selecione todos esses contatos de contatos de contatos. Cada contato tem muitos correios de contato, então coloque -os em um único IEnumerable coleção de tipo ContactDetail

.Where(x => x.ID == Guid.Empty): ... mas apenas aqueles contactDetails com um ID vazio

.SelectMany(x => x.Contacts);: Agora selecione cada um dos muitos contatos dos contatos do ContactDetails. No entanto, como o compilador sabe que existe uma relação um para muitos entre contatos e contactDetails (e não o contrário), essa afirmação não é possível e, portanto, mostra um erro de compilação

Outras dicas

Estou interpretando sua consulta pretendida como "de vários grupos de contatos, selecione todos os contatos que possuem id = guid.Empty e também têm detalhes que todos têm id = guid.empty".

A maneira como seu código é realmente interpretado é "de todos os contatos que possuem Guid.Empty, selecione todos os detalhes que têm Guid.Empty e, com esses detalhes, selecione todos os contatos". O primeiro problema é que você acaba selecionando a partir dos detalhes. Isso significa o final SelectMany devia ser um Select, Porque x.Contacts Aqui refere-se ao relacionamento muitos para um dos detalhes aos contatos.

O segundo problema é que o resultado conterá duplicatas de contatos, porque o mesmo contato está incluído para cada detalhes. O que você deve fazer é filtrar os contatos diretamente com base em suas coleções de detalhes, como esta:

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

Observe que isso também selecionaria contatos com detalhes zero, o que é um comportamento diferente da sua consulta, por isso não tenho certeza se é o que você deseja. Você pode adicionar outro filtro para ContactDetails.Any() se não.

Editar: Como você está usando a estrutura da entidade, provavelmente não funcionará. Pode ser necessário selecionar os detalhes em uma subconsulta e filtrar na memória depois que ele executar:

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);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top