Respuestas:
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.
fea_Features.Where(s => selectedFeatures.Contains(s.feaId))
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).
Iré por Inner Join en este contexto. Si hubiera usado contiene, iteraría 6 veces a pesar de que solo haya una coincidencia.
var desiredNames = new[] { "Pankaj", "Garg" };
var people = new[]
{
new { FirstName="Pankaj", Surname="Garg" },
new { FirstName="Marc", Surname="Gravell" },
new { FirstName="Jeff", Surname="Atwood" }
};
var records = (from p in people join filtered in desiredNames on p.FirstName equals filtered select p.FirstName).ToList();
Supongamos que tengo dos objetos de lista.
List 1 List 2
1 12
2 7
3 8
4 98
5 9
6 10
7 6
Usando Contiene, buscará cada elemento de la Lista 1 en la Lista 2, lo que significa que la iteración ocurrirá 49 veces.
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í:
Queue<Guid> productIds = new Queue<Guid>(Products.Select(p => p.Key));
if(productIds.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.ProductId = Guid\'{1}\'", entities.Products.Name, productIds.Dequeue());
while(productIds.Count > 0)
{
sb.AppendFormat(" OR {0}.ProductId = Guid\'{1}\'",
entities.Products.Name, productIds.Dequeue());
}
}
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:
Los tipos de argumento 'Edm.Guid' y 'Edm.String' son incompatibles para esta operación., Casi igual a expresión, línea 6, columna 14.
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. :)
Un método alternativo a la respuesta de BenAlabaster
En primer lugar, puede volver a escribir la consulta de esta manera:
var matches = from Users in people
where Users.User_Rights == "Admin" ||
Users.User_Rights == "Users" ||
Users.User_Rights == "Limited"
select Users;
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:
var matches = ctx.People.Where(
BuildOrExpression<People, string>(
p => p.User_Rights, names
)
);
Esto genera una expresión que tiene el mismo efecto que:
var matches = from p in ctx.People
where names.Contains(p.User_Rights)
select p;
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:
public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(
Expression<Func<TElement, TValue>> valueSelector,
IEnumerable<TValue> values
)
{
if (null == valueSelector)
throw new ArgumentNullException("valueSelector");
if (null == values)
throw new ArgumentNullException("values");
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
return e => false;
var equals = values.Select(value =>
(Expression)Expression.Equal(
valueSelector.Body,
Expression.Constant(
value,
typeof(TValue)
)
)
);
var body = equals.Aggregate<Expression>(
(accumulate, equal) => Expression.Or(accumulate, equal)
);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
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
Ejemplo real:
var trackList = Model.TrackingHistory.GroupBy(x => x.ShipmentStatusId).Select(x => x.Last()).Reverse();
List<int> done_step1 = new List<int>() {2,3,4,5,6,7,8,9,10,11,14,18,21,22,23,24,25,26 };
bool isExists = trackList.Where(x => done_step1.Contains(x.ShipmentStatusId.Value)).FirstOrDefault() != null;
¿Seriamente? Ustedes nunca han usado
where (t.MyTableId == 1 || t.MyTableId == 2 || t.MyTableId == 3)
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 entonces where (x == 1 || x == 2 || x == 3)
?