¿Hay alguna forma de comparar cadenas en una expresión C # LINQ similar al LIKEoperador de SQL ?
Supongamos que tengo una lista de cadenas. En esta lista quiero buscar una cadena. En SQL, podría escribir:
SELECT * FROM DischargePort WHERE PortName LIKE '%BALTIMORE%'
En lugar de lo anterior, la consulta quiere una sintaxis linq.
using System.Text.RegularExpressions;
…
var regex = new Regex(sDischargePort, RegexOptions.IgnoreCase);
var sPortCode = Database.DischargePorts
.Where(p => regex.IsMatch(p.PortName))
.Single().PortCode;
Mi sintaxis LINQ anterior no funciona. ¿Qué me he equivocado?

Respuestas:
Normalmente usa
String.StartsWith/EndsWith/Contains. Por ejemplo:var portCode = Database.DischargePorts .Where(p => p.PortName.Contains("BALTIMORE")) .Single() .PortCode;Sin embargo, no sé si hay una forma de hacer expresiones regulares adecuadas a través de LINQ to SQL. (Tenga en cuenta que realmente depende del proveedor que esté utilizando; estaría bien en LINQ to Objects; es una cuestión de si el proveedor puede convertir la llamada a su formato de consulta nativo, por ejemplo, SQL).
EDITAR: Como dice BitKFu,
Singledebe usarse cuando espera exactamente un resultado, cuando es un error para que ese no sea el caso. Opciones deSingleOrDefault,FirstOrDefaultoFirstdeberían usarse dependiendo exactamente de lo que se espera.fuente
Single(),SingleOrDefault()sería mi próximo paso, a menos que comprendamos el contexto completo ...¿Regex? No. Pero para esa consulta puedes usar:
string filter = "BALTIMORE"; (blah) .Where(row => row.PortName.Contains(filter)) (blah)Si realmente desea SQL
LIKE, puede usarSystem.Data.Linq.SqlClient.SqlMethods.Like(...), a qué asigna LINQ-to-SQLLIKEen SQL Server.fuente
Bueno ... a veces puede ser incómodo de usar
Contains,StartsWithoEndsWithespecialmente cuando se busca un valor de determinación,LIKEpor ejemplo, el 'valor%' pasado requiere que el desarrollador use laStartsWithfunción en la expresión. Entonces decidí escribir extensión paraIQueryableobjetos.Uso
// numbers: 11-000-00, 00-111-00, 00-000-11 var data1 = parts.Like(p => p.Number, "%11%"); // result: 11-000-00, 00-111-00, 00-000-11 var data2 = parts.Like(p => p.Number, "11%"); // result: 11-000-00 var data3 = parts.Like(p => p.Number, "%11"); // result: 00-000-11Código
public static class LinqEx { private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains"); private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) }); public static Expression<Func<TSource, bool>> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> property, string value) { var param = Expression.Parameter(typeof(TSource), "t"); var propertyInfo = GetPropertyInfo(property); var member = Expression.Property(param, propertyInfo.Name); var startWith = value.StartsWith("%"); var endsWith = value.EndsWith("%"); if (startWith) value = value.Remove(0, 1); if (endsWith) value = value.Remove(value.Length - 1, 1); var constant = Expression.Constant(value); Expression exp; if (endsWith && startWith) { exp = Expression.Call(member, ContainsMethod, constant); } else if (startWith) { exp = Expression.Call(member, EndsWithMethod, constant); } else if (endsWith) { exp = Expression.Call(member, StartsWithMethod, constant); } else { exp = Expression.Equal(member, constant); } return Expression.Lambda<Func<TSource, bool>>(exp, param); } public static IQueryable<TSource> Like<TSource, TMember>(this IQueryable<TSource> source, Expression<Func<TSource, TMember>> parameter, string value) { return source.Where(LikeExpression(parameter, value)); } private static PropertyInfo GetPropertyInfo(Expression expression) { var lambda = expression as LambdaExpression; if (lambda == null) throw new ArgumentNullException("expression"); MemberExpression memberExpr = null; switch (lambda.Body.NodeType) { case ExpressionType.Convert: memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression; break; case ExpressionType.MemberAccess: memberExpr = lambda.Body as MemberExpression; break; } if (memberExpr == null) throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression."); var output = memberExpr.Member as PropertyInfo; if (output == null) throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression."); return output; } }fuente
IEnumerable?Como ya mencionaron Jon Skeet y Marc Gravell, simplemente puede tomar una condición contiene. Pero en el caso de su consulta similar, es muy peligroso tomar una declaración Single (), porque eso implica que solo encuentra 1 resultado. En caso de obtener más resultados, recibirá una buena excepción :)
Entonces preferiría usar FirstOrDefault () en lugar de Single ():
var first = Database.DischargePorts.FirstOrDefault(p => p.PortName.Contains("BALTIMORE")); var portcode = first != null ? first.PortCode : string.Empty;fuente
En LINQ nativo, puede utilizar una combinación de
Contains/StartsWith/EndsWitho RegExp.En el método de uso de LINQ2SQL
SqlMethods.Like()from i in db.myTable where SqlMethods.Like(i.field, "tra%ata") select iagregue Ensamblado: System.Data.Linq (en System.Data.Linq.dll) para usar esta función.
fuente
StartsWith(),Contains(), etc, qué no trabajo con Linq2SQL (al menos me sale "La expresión LINQ ... no se podría traducir ..." y una instrucción para el uso ToList () para "evaluación del cliente", lo que yo' . m Nota haciendo ya, en EF Core, se trasladó aEF.Functions.Like().Where(e => e.Value.StartsWith("BALTIMORE"))Esto funciona como "LIKE" de SQL ...
fuente
Tan simple como esto
string[] users = new string[] {"Paul","Steve","Annick","Yannick"}; var result = from u in users where u.Contains("nn") select u;Resultado -> Annick, Yannick
fuente
Puede llamar al método único con un predicado:
var portCode = Database.DischargePorts .Single(p => p.PortName.Contains("BALTIMORE")) .PortCode;fuente
Lo ideal sería utilizar
StartWithoEndWith.Aquí hay un ejemplo:
DataContext dc = new DCGeneral(); List<Person> lstPerson= dc.GetTable<Person>().StartWith(c=> c.strNombre).ToList(); return lstPerson;fuente
public static class StringEx { public static bool Contains(this String str, string[] Arr, StringComparison comp) { if (Arr != null) { foreach (string s in Arr) { if (str.IndexOf(s, comp)>=0) { return true; } } } return false; } public static bool Contains(this String str,string[] Arr) { if (Arr != null) { foreach (string s in Arr) { if (str.Contains(s)) { return true; } } } return false; } } var portCode = Database.DischargePorts .Single(p => p.PortName.Contains( new string[] {"BALTIMORE"}, StringComparison.CurrentCultureIgnoreCase) )) .PortCode;fuente
Simplemente agregue a los métodos de extensión de objetos de cadena.
public static class StringEx { public static bool Contains(this String str, string[] Arr, StringComparison comp) { if (Arr != null) { foreach (string s in Arr) { if (str.IndexOf(s, comp)>=0) { return true; } } } return false; } public static bool Contains(this String str,string[] Arr) { if (Arr != null) { foreach (string s in Arr) { if (str.Contains(s)) { return true; } } } return false; } }uso:
use namespase that contains this class; var sPortCode = Database.DischargePorts .Where(p => p.PortName.Contains(new string [] {"BALTIMORE"}, StringComparison.CurrentCultureIgnoreCase) ) .Single().PortCode;fuente
List<Categories> categoriess; private void Buscar() { try { categoriess = Contexto.Categories.ToList(); categoriess = categoriess.Where(n => n.CategoryID >= Convert.ToInt32(txtCatID.Text) && n.CategoryID <= Convert.ToInt32(txtCatID1.Text) && (n.CategoryName.Contains(txtCatName.Text)) ).ToList();fuente
@adobrzyc tenía esta gran
LIKEfunción personalizada , solo quería compartir laIEnumerableversión.public static class LinqEx { private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains"); private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) }); private static Func<TSource, bool> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> property, string value) { var param = Expression.Parameter(typeof(TSource), "t"); var propertyInfo = GetPropertyInfo(property); var member = Expression.Property(param, propertyInfo.Name); var startWith = value.StartsWith("%"); var endsWith = value.EndsWith("%"); if (startWith) value = value.Remove(0, 1); if (endsWith) value = value.Remove(value.Length - 1, 1); var constant = Expression.Constant(value); Expression exp; if (endsWith && startWith) { exp = Expression.Call(member, ContainsMethod, constant); } else if (startWith) { exp = Expression.Call(member, EndsWithMethod, constant); } else if (endsWith) { exp = Expression.Call(member, StartsWithMethod, constant); } else { exp = Expression.Equal(member, constant); } return Expression.Lambda<Func<TSource, bool>>(exp, param).Compile(); } public static IEnumerable<TSource> Like<TSource, TMember>(this IEnumerable<TSource> source, Expression<Func<TSource, TMember>> parameter, string value) { return source.Where(LikeExpression(parameter, value)); } private static PropertyInfo GetPropertyInfo(Expression expression) { var lambda = expression as LambdaExpression; if (lambda == null) throw new ArgumentNullException("expression"); MemberExpression memberExpr = null; switch (lambda.Body.NodeType) { case ExpressionType.Convert: memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression; break; case ExpressionType.MemberAccess: memberExpr = lambda.Body as MemberExpression; break; } if (memberExpr == null) throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression."); var output = memberExpr.Member as PropertyInfo; if (output == null) throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression."); return output; } }fuente