Pergunta

Eu tenho uma consulta linq envolvendo as três entidades a seguir:

public class LandPoint
{
    ...
    public OlsonTimeZone TimeZone { get; set; }
}

public class OlsonTimeZone : TimeZone
{
    ...
    public virtual ICollection<WindowsTimeZone> Windows { get; set; }
}

public class WindowsTimeZone : TimeZone
{
    ...
    public virtual ICollection<OlsonTimeZone> Olson { get; set; }
}

Portanto, um LandPoint possui um OlsonTimeZone que possui zero ou mais WindowsTimeZones.

O que estou tentando fazer é obter o nome WindowsTimeZone (prefixado por 'Windows:') se OlsonTimeZone tiver algum WindowsTimeZones ou o nome OlsonTimeZone (prefixado por 'Olson:') como um substituto junto com informações sobre o ponto em si.

O que escrevi é:

 return db.LandPoints.Where(x => x.GeoNameID == ID).Take(1).Select(x => new LandPoint
        {
            TimeZone = x.TimeZone
                            .Windows.Select(t => "Windows:" + x.Name)
                            .Union(new[] { "Olson:" + x.TimeZone.Name })
                            .FirstOrDefault()
        }).First();

O que deveria, em teoria, fazer o que eu quero.Exceto que, para um determinado ponto com o qual testei (que sei que tem um WindowsTimeZone associado), ele retornou OlsonTimeZone em vez de WindowsTimeZone.Se para o mesmo ID eu escrevo o seguinte:

return db.LandPoints.Where(x => x.GeoNameID == ID).Take(1).Select(x => new LandPoint
        {
            TimeZone = x.TimeZone
                            .Windows.Select(t => "Windows:" + x.Name)
                            .FirstOrDefault()
        }).First();

Eu recebo o WindowsTimeZone.

Tenho certeza de que poderia reescrevê-lo usando uma instrução CASE, mas achei que era mais elegante.Como o modo como ele se comporta é um tanto contra-intuitivo e entender por que ele está fazendo o que faz me ajudaria a ter uma noção melhor de como as consultas linq são traduzidas para sql, decidi postar uma pergunta aqui.

Então, por que está fazendo o que faz?Existe alguma adição ao código acima que o faria funcionar (mantendo a instrução UNION)?

Desde já, obrigado John

Foi útil?

Solução

É porque a união não garante a ordem.Você não pode colocar expectativas especiais com base na ordem dos itens sem encomendá-los.Mas seu código deve disparar NotSupportedException porque isso não é permitido: db.LandPoints.Select(x => new LandPoint ...

Se você tem LandPoint entidade mapeada pela estrutura de entidade, você não pode projetar para este tipo em Linq-to-entities.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top