query inner framework consulta .net sql-server entity-framework linq-to-entities

.net - inner - ¿Te gusta Operador en Entity Framework?



linq inner join c# entity framework (9)

Estamos intentando implementar el operador "LIKE" en Entity Framework para nuestras entidades con campos de cadena, pero no parece ser compatible. ¿Alguien más ha intentado hacer algo como esto?

Esta publicación de blog resume el problema que estamos teniendo. Podríamos usar contiene, pero eso solo coincide con el caso más trivial de LIKE. La combinación de contains, startswith, endswith e indexof nos lleva allí, pero requiere una traducción entre comodines estándar y el código Linq to Entities.


Actualización: en EF 6.2 hay un operador similar

Where(i => DbFunctions.Like(searchstring ,like expression)


En realidad, no sé nada sobre EF, pero en LINQ to SQL generalmente expresas una cláusula LIKE usando String. Contiene:

where entity.Name.Contains("xyz")

se traduce a

WHERE Name LIKE ''%xyz%''

(Use StartsWith y EndsWith para otro comportamiento).

No estoy del todo seguro de si eso es útil, porque no entiendo a qué te refieres cuando dices que intentas implementar LIKE. Si he entendido mal por completo, házmelo saber y borraré esta respuesta :)


Esta es una publicación anterior ahora, pero para cualquiera que busque la respuesta, este enlace debería ayudar.

Version corta:

Método SqlFunctions.PatIndex - devuelve la posición de inicio de la primera aparición de un patrón en una expresión específica, o ceros si no se encuentra el patrón, en todos los tipos de datos válidos de texto y caracteres

Espacio de nombres: System.Data.Objects.SqlClient Assembly: System.Data.Entity (en System.Data.Entity.dll)

Una pequeña explicación también aparece en este hilo del foro .


Hay un operador LIKE agregado en Entity Framework Core 2.0 :

var query = from e in _context.Employees where EF.Functions.Like(e.Title, "%developer%") select e;

Comparando con ... where e.Title.Contains("developer") ... realmente se traduce a SQL LIKE lugar de a CHARINDEX que vemos para el método Contains .


Puede usar un real como en Enlace a entidades con bastante facilidad

Añadir

<Function Name="String_Like" ReturnType="Edm.Boolean"> <Parameter Name="searchingIn" Type="Edm.String" /> <Parameter Name="lookingFor" Type="Edm.String" /> <DefiningExpression> searchingIn LIKE lookingFor </DefiningExpression> </Function>

a tu EDMX en esta etiqueta:

edmx: Edmx / edmx: Runtime / edmx: ConceptualModels / Schema

Recuerde también el espacio de nombres en el atributo <schema namespace="" />

A continuación, agregue una clase de extensión en el espacio de nombres anterior:

public static class Extensions { [EdmFunction("DocTrails3.Net.Database.Models", "String_Like")] public static Boolean Like(this String searchingIn, String lookingFor) { throw new Exception("Not implemented"); } }

Este método de extensión ahora se asignará a la función EDMX.

Más información aquí: http://jendaperl.blogspot.be/2011/02/like-in-linq-to-entities.html


Se menciona específicamente en la documentación como parte de Entity SQL. ¿Está recibiendo un mensaje de error?

// LIKE and ESCAPE // If an AdventureWorksEntities.Product contained a Name // with the value ''Down_Tube'', the following query would find that // value. Select value P.Name FROM AdventureWorksEntities.Product as P where P.Name LIKE ''DownA_%'' ESCAPE ''A'' // LIKE Select value P.Name FROM AdventureWorksEntities.Product as P where P.Name like ''BB%''

http://msdn.microsoft.com/en-us/library/bb399359.aspx


Yo tuve el mismo problema.

Por ahora, me he conformado con el filtro Wildcard / Regex del lado del cliente basado en http://www.codeproject.com/Articles/11556/Converting-Wildcards-to-Regexes?msg=1423024#xx1423024xx - es simple y funciona como esperado.

He encontrado otra discusión sobre este tema: http://forums.asp.net/t/1654093.aspx/2/10
Esta publicación parece prometedora si usa Entity Framework> = 4.0:

Use SqlFunctions.PatIndex:

http://msdn.microsoft.com/spaindex.aspx

Me gusta esto:

var q = EFContext.Products.Where(x => SqlFunctions.PatIndex("%CD%BLUE%", x.ProductName) > 0);

Nota: esta solución es solo para SQL-Server, porque usa una función PATINDEX no estándar.


re: "nos gustaría poder coincidir en bla bla bla foo bar foo? bar? foo * y otros patrones complejos". No he intentado esto (no lo he necesitado todavía), pero ¿ha intentado usar System.Text.RegularExpressions.RegEx?


si está utilizando MS Sql, he escrito 2 métodos de extensión para admitir el carácter% para la búsqueda de comodines. (Se requiere LinqKit)

public static class ExpressionExtension { public static Expression<Func<T, bool>> Like<T>(Expression<Func<T, string>> expr, string likeValue) { var paramExpr = expr.Parameters.First(); var memExpr = expr.Body; if (likeValue == null || likeValue.Contains(''%'') != true) { Expression<Func<string>> valExpr = () => likeValue; var eqExpr = Expression.Equal(memExpr, valExpr.Body); return Expression.Lambda<Func<T, bool>>(eqExpr, paramExpr); } if (likeValue.Replace("%", string.Empty).Length == 0) { return PredicateBuilder.True<T>(); } likeValue = Regex.Replace(likeValue, "%+", "%"); if (likeValue.Length > 2 && likeValue.Substring(1, likeValue.Length - 2).Contains(''%'')) { likeValue = likeValue.Replace("[", "[[]").Replace("_", "[_]"); Expression<Func<string>> valExpr = () => likeValue; var patExpr = Expression.Call(typeof(SqlFunctions).GetMethod("PatIndex", new[] { typeof(string), typeof(string) }), valExpr.Body, memExpr); var neExpr = Expression.NotEqual(patExpr, Expression.Convert(Expression.Constant(0), typeof(int?))); return Expression.Lambda<Func<T, bool>>(neExpr, paramExpr); } if (likeValue.StartsWith("%")) { if (likeValue.EndsWith("%") == true) { likeValue = likeValue.Substring(1, likeValue.Length - 2); Expression<Func<string>> valExpr = () => likeValue; var containsExpr = Expression.Call(memExpr, typeof(String).GetMethod("Contains", new[] { typeof(string) }), valExpr.Body); return Expression.Lambda<Func<T, bool>>(containsExpr, paramExpr); } else { likeValue = likeValue.Substring(1); Expression<Func<string>> valExpr = () => likeValue; var endsExpr = Expression.Call(memExpr, typeof(String).GetMethod("EndsWith", new[] { typeof(string) }), valExpr.Body); return Expression.Lambda<Func<T, bool>>(endsExpr, paramExpr); } } else { likeValue = likeValue.Remove(likeValue.Length - 1); Expression<Func<string>> valExpr = () => likeValue; var startsExpr = Expression.Call(memExpr, typeof(String).GetMethod("StartsWith", new[] { typeof(string) }), valExpr.Body); return Expression.Lambda<Func<T, bool>>(startsExpr, paramExpr); } } public static Expression<Func<T, bool>> AndLike<T>(this Expression<Func<T, bool>> predicate, Expression<Func<T, string>> expr, string likeValue) { var andPredicate = Like(expr, likeValue); if (andPredicate != null) { predicate = predicate.And(andPredicate.Expand()); } return predicate; } public static Expression<Func<T, bool>> OrLike<T>(this Expression<Func<T, bool>> predicate, Expression<Func<T, string>> expr, string likeValue) { var orPredicate = Like(expr, likeValue); if (orPredicate != null) { predicate = predicate.Or(orPredicate.Expand()); } return predicate; } }

uso

var orPredicate = PredicateBuilder.False<People>(); orPredicate = orPredicate.OrLike(per => per.Name, "He%llo%"); orPredicate = orPredicate.OrLike(per => per.Name, "%Hi%"); var predicate = PredicateBuilder.True<People>(); predicate = predicate.And(orPredicate.Expand()); predicate = predicate.AndLike(per => per.Status, "%Active"); var list = dbContext.Set<People>().Where(predicate.Expand()).ToList();

en ef6 y debe traducirse a

.... from People per where ( patindex(@p__linq__0, per.Name) <> 0 or per.Name like @p__linq__1 escape ''~'' ) and per.Status like @p__linq__2 escape ''~''

'', @ p__linq__0 =''% He% llo% '', @ p__linq__1 =''% Hi% '', @ p__linq_2 =''% Active ''