No T-SQL, você poderia ter uma consulta como:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
Como você replicaria isso em uma consulta LINQ to Entities? Isso é possível?
fonte
No T-SQL, você poderia ter uma consulta como:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
Como você replicaria isso em uma consulta LINQ to Entities? Isso é possível?
Você precisa invertê-lo em termos da maneira como pensa sobre isso. Em vez de "entrar" para encontrar os direitos de usuário do item atual em um conjunto predefinido de direitos de usuário aplicáveis, você está solicitando a um conjunto predefinido de direitos de usuário se ele contém o valor aplicável do item atual. É exatamente da mesma maneira que você encontraria um item em uma lista regular no .NET.
Há duas maneiras de fazer isso usando o LINQ, um usa a sintaxe da consulta e o outro usa a sintaxe do método. Essencialmente, eles são iguais e podem ser usados alternadamente, dependendo da sua preferência:
Sintaxe da consulta:
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
Sintaxe do método:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
Minha preferência pessoal nesse caso pode ser a sintaxe do método, porque, em vez de atribuir a variável, eu poderia fazer o foreach em uma chamada anônima como esta:
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Sintaticamente, isso parece mais complexo, e você precisa entender o conceito de expressões ou delegados lambda para realmente descobrir o que está acontecendo, mas, como você pode ver, isso condensa o código em uma quantidade razoável.
Tudo se resume ao seu estilo e preferência de codificação - todos os três exemplos fazem a mesma coisa de maneira um pouco diferente.
Uma maneira alternativa nem usa o LINQ, você pode usar a mesma sintaxe de método substituindo "where" por "FindAll" e obter o mesmo resultado, que também funcionará no .NET 2.0:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Isso deve bastar para o seu propósito. Ele compara duas coleções e verifica se uma coleção tem os valores correspondentes aos da outra coleção
fonte
Se você estiver usando o VS2008 / .net 3.5, consulte a dica 8 de Alex James: http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style -queries-using-linq-to-entity.aspx
Caso contrário, basta usar o método array.Contains (someEntity.Member).
fonte
Eu irei para o Inner Join neste contexto. Se eu tivesse usado contém, ele iria repetir 6 vezes, apesar do fato de haver apenas uma correspondência.
Desvantagens de Contém
Suponha que eu tenha dois objetos de lista.
Usando Contém, ele procurará cada item da Lista 1 na Lista 2, o que significa que a iteração ocorrerá 49 vezes !!!
fonte
Essa pode ser a maneira possível pela qual você pode usar diretamente os métodos de extensão LINQ para verificar a cláusula
fonte
Também tentei trabalhar com algo semelhante ao SQL-IN - consultando um modelo de dados de entidade . Minha abordagem é um construtor de strings para compor uma grande expressão OR. Isso é terrivelmente feio, mas receio que seja o único caminho a seguir agora.
Agora, bem, isso é assim:
Trabalhando com GUIDs neste contexto : Como você pode ver acima, sempre há a palavra "GUID" antes do GUID se nos fragmentos de string de consulta. Se você não adicionar isso,
ObjectQuery<T>.Where
lança a seguinte exceção:Encontrou isso nos fóruns do MSDN, pode ser útil ter em mente.
Matthias
... ansioso pela próxima versão do .NET e Entity Framework, quando tudo melhorar. :)
fonte
Um método alternativo para a resposta do BenAlabaster
Primeiro de tudo, você pode reescrever a consulta assim:
Certamente isso é mais 'prolixo' e uma dor de escrever, mas funciona da mesma forma.
Portanto, se tivéssemos algum método utilitário que facilitasse a criação desse tipo de expressão LINQ, estaríamos nos negócios.
com um método utilitário no lugar, você pode escrever algo como isto:
Isso cria uma expressão que tem o mesmo efeito que:
Mas o que é mais importante, na verdade, funciona no .NET 3.5 SP1.
Aqui está a função de encanamento que torna isso possível:
Não vou tentar explicar esse método, exceto dizer que ele basicamente constrói uma expressão de predicado para todos os valores usando o valueSelector (ou seja, p => p.User_Rights) e ORs esses predicados juntos para criar uma expressão para o completo predicado
Fonte: http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
fonte
Exemplo real:
fonte
Seriamente? Vocês nunca usaram
fonte
Checks = NumValues * NumRows
. Como esse é um cálculo do tipo M * N, se um for pequeno, o tempo para executar cada verificação necessária também será pequeno. Eu adicionei a restrição para que o cjm30305 soubesse como configurar um ambiente de teste onde mostrasse por que sua solução é ruim.where new[] { 1, 2, 3 }.Contains(x)
faz menos comparações, entãowhere (x == 1 || x == 2 || x == 3)
?