En T-SQL podría tener una consulta como:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
¿Cómo replicaría eso en una consulta LINQ to Entities? ¿Es posible?
fuente
En T-SQL podría tener una consulta como:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
¿Cómo replicaría eso en una consulta LINQ to Entities? ¿Es posible?
Debes darle la vuelta en términos de la forma en que piensas al respecto. En lugar de hacer "in" para encontrar los derechos de usuario del elemento actual en un conjunto predefinido de derechos de usuario aplicables, está solicitando un conjunto predefinido de derechos de usuario si contiene el valor aplicable del elemento actual. Esta es exactamente la misma forma en que encontraría un elemento en una lista regular en .NET.
Hay dos formas de hacerlo usando LINQ, una usa la sintaxis de consulta y la otra usa la sintaxis de método. Esencialmente, son iguales y podrían usarse indistintamente según su preferencia:
Sintaxis de 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;
}
Método de sintaxis:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
Mi preferencia personal en esta instancia podría ser la sintaxis del método porque en lugar de asignar la variable, podría hacer el foreach sobre una llamada 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;
}
Sintácticamente, esto parece más complejo, y hay que entender el concepto de expresiones lambda o delegados para entender realmente lo que está sucediendo, pero como puede ver, esto condensa el código bastante.
Todo se reduce a su estilo y preferencia de codificación: mis tres ejemplos hacen lo mismo de manera ligeramente diferente.
Una forma alternativa ni siquiera usa LINQ, puede usar la misma sintaxis de método reemplazando "where" con "FindAll" y obtener el mismo resultado, que también funcionará en .NET 2.0:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Esto debería ser suficiente para su propósito. Compara dos colecciones y comprueba si una colección tiene los valores que coinciden con los de la otra colección.
fuente
Si está utilizando VS2008 / .net 3.5, consulte el consejo # 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
De lo contrario, simplemente use el método array.Contains (someEntity.Member).
fuente
Iré por Inner Join en este contexto. Si hubiera usado contiene, iteraría 6 veces a pesar de que solo haya una coincidencia.
Desventajas de Contiene
Supongamos que tengo dos objetos de lista.
Usando Contiene, buscará cada elemento de la Lista 1 en la Lista 2, lo que significa que la iteración ocurrirá 49 veces.
fuente
Esta podría ser la forma posible de utilizar directamente los métodos de extensión LINQ para verificar la cláusula in
fuente
También intenté trabajar con algo parecido a SQL-IN: consultar un modelo de datos de entidad . Mi enfoque es un generador de cadenas para componer una gran expresión OR. Eso es terriblemente feo, pero me temo que es la única forma de hacerlo en este momento.
Ahora bien, eso se ve así:
Trabajar con GUID en este contexto : como puede ver arriba, siempre existe la palabra "GUID" antes del GUID si se encuentra en los fragmentos de la cadena de consulta. Si no agrega esto,
ObjectQuery<T>.Where
lanza la siguiente excepción:Encontré esto en los foros de MSDN, podría ser útil tenerlo en cuenta.
Matías
... esperando la próxima versión de .NET y Entity Framework, cuando todo mejore. :)
fuente
Un método alternativo a la respuesta de BenAlabaster
En primer lugar, puede volver a escribir la consulta de esta manera:
Ciertamente, esto es más 'prolijo' y un dolor de escritura, pero funciona de todos modos.
Entonces, si tuviéramos algún método de utilidad que facilitara la creación de este tipo de expresiones LINQ estaríamos en el negocio.
Con un método de utilidad en su lugar, puede escribir algo como esto:
Esto genera una expresión que tiene el mismo efecto que:
Pero lo que es más importante en realidad funciona contra .NET 3.5 SP1.
Aquí está la función de fontanería que hace esto posible:
No voy a intentar explicar este método, aparte de decir que esencialmente construye una expresión de predicado para todos los valores usando valueSelector (es decir, p => p.User_Rights) y ORs esos predicados juntos para crear una expresión para el completo predicado
Fuente: http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
fuente
Ejemplo real:
fuente
¿Seriamente? Ustedes nunca han usado
fuente
Checks = NumValues * NumRows
. Debido a que este es un cálculo de tipo M * N, si cualquiera es pequeño, el tiempo para realizar cada verificación requerida también será pequeño. Agregué la restricción para que cjm30305 supiera cómo configurar un entorno de prueba que muestre por qué su solución es pobre.where new[] { 1, 2, 3 }.Contains(x)
hace menos comparaciones entonceswhere (x == 1 || x == 2 || x == 3)
?