Comme opérateur dans Entity Framework?

Nous essayons d'implémenter l'opérateur "LIKE" dans Entity Framework pour nos entités avec des champs de type string, mais cela ne semble pas être supporté. Est-ce que quelqu'un d'autre a essayé de faire quelque chose comme ça?

Ce billet résume le problème que nous avons. Nous pourrions utiliser contains, mais cela ne correspond qu'au cas le plus sortingvial pour LIKE. La combinaison contient, beginwith, endswith et indexof nous y amène, mais nécessite une traduction entre les caractères generics standard et le code Linq to Entities.

Ceci est un ancien post maintenant, mais pour tous ceux qui cherchent la réponse, ce lien devrait aider:

http://msdn.microsoft.com/en-us/library/system.data.objects.sqlclient.sqlfunctions.patindex.aspx

SqlFunctions.PatIndex, méthode – Retourne la position de départ de la première occurrence d'un motif dans une expression spécifiée, ou des zéros si le motif n'est pas trouvé, sur tous les types de données de text et de caractère valides

Espace de noms: System.Data.Objects.SqlClient Assembly: System.Data.Entity (dans System.Data.Entity.dll)

Un peu d'explication apparaît dans ce fil de discussion du forum:

http://social.msdn.microsoft.com/Forums/en-US/lightswitch/thread/5ede2db0-a4f9-4178-84c0-fabf4d3a57fa

Je ne connais pas vraiment EF, mais dans LINQ to SQL vous exprimez généralement une clause LIKE en utilisant Ssortingng.Contains:

where entity.Name.Contains("xyz") 

Se traduit par

 WHERE Name LIKE '%xyz%' 

(Utilisez StartsWith et EndsWith pour tout autre comportement.)

Je ne suis pas tout à fait certain si cela est utile, parce que je ne comprends pas ce que vous voulez dire lorsque vous dites que vous essayez de mettre en œuvre LIKE. Si j'ai mal compris complètement, faites le moi savoir et je vais supprimer cette réponse 🙂

J'ai eu le même problème.

Pour l'instant, je me suis installé avec le filtrage côté client Wildcard / Regex basé sur http://www.codeproject.com/Articles/11556/Converting-Wildcards-to-Regexes?msg=1423024#xx1423024xx – c'est simple et fonctionne comme attendu.

J'ai trouvé une autre discussion sur ce sujet: http://forums.asp.net/t/1654093.aspx/2/10
Ce message semble prometteur si vous utilisez Entity Framework> = 4.0:

Utilisez SqlFunctions.PatIndex:

http://msdn.microsoft.com/en-us/library/system.data.objects.sqlclient.sqlfunctions.patindex.aspx

Comme ça:

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

Remarque: cette solution est uniquement destinée à SQL Server, car elle utilise une fonction PATINDEX non standard.

Il est spécifiquement mentionné dans la documentation dans le cadre d'Entity SQL. Recevez-vous un message d'erreur?

 // 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

L'opérateur LIKE est ajouté dans Entity Framework Core 2.0 :

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

En comparant à ... where e.Title.Contains("developer") ... il est vraiment traduit en SQL LIKE plutôt que CHARINDEX que nous voyons pour la méthode Contains .

Si vous utilisez MS SQL, j'ai écrit 2 methods d'extension pour supporter le caractère% pour la search générique. (LinqKit est requirejs)

 public static class ExpressionExtension { public static Expression<Func<T, bool>> Like<T>(Expression<Func<T, ssortingng>> expr, ssortingng likeValue) { var paramExpr = expr.Parameters.First(); var memExpr = expr.Body; if (likeValue == null || likeValue.Contains('%') != true) { Expression<Func<ssortingng>> valExpr = () => likeValue; var eqExpr = Expression.Equal(memExpr, valExpr.Body); return Expression.Lambda<Func<T, bool>>(eqExpr, paramExpr); } if (likeValue.Replace("%", ssortingng.Empty).Length == 0) { return PredicateBuilder.True<T>(); } likeValue = Regex.Replace(likeValue, "%+", "%"); if (likeValue.Length > 2 && likeValue.Subssortingng(1, likeValue.Length - 2).Contains('%')) { likeValue = likeValue.Replace("[", "[[]").Replace("_", "[_]"); Expression<Func<ssortingng>> valExpr = () => likeValue; var patExpr = Expression.Call(typeof(SqlFunctions).GetMethod("PatIndex", new[] { typeof(ssortingng), typeof(ssortingng) }), 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.Subssortingng(1, likeValue.Length - 2); Expression<Func<ssortingng>> valExpr = () => likeValue; var containsExpr = Expression.Call(memExpr, typeof(Ssortingng).GetMethod("Contains", new[] { typeof(ssortingng) }), valExpr.Body); return Expression.Lambda<Func<T, bool>>(containsExpr, paramExpr); } else { likeValue = likeValue.Subssortingng(1); Expression<Func<ssortingng>> valExpr = () => likeValue; var endsExpr = Expression.Call(memExpr, typeof(Ssortingng).GetMethod("EndsWith", new[] { typeof(ssortingng) }), valExpr.Body); return Expression.Lambda<Func<T, bool>>(endsExpr, paramExpr); } } else { likeValue = likeValue.Remove(likeValue.Length - 1); Expression<Func<ssortingng>> valExpr = () => likeValue; var startsExpr = Expression.Call(memExpr, typeof(Ssortingng).GetMethod("StartsWith", new[] { typeof(ssortingng) }), 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, ssortingng>> expr, ssortingng 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, ssortingng>> expr, ssortingng likeValue) { var orPredicate = Like(expr, likeValue); if (orPredicate != null) { predicate = predicate.Or(orPredicate.Expand()); } return predicate; } } 

usage

 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 et il devrait se traduire par

 .... 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 ='% Actif '

Mise à jour: Dans EF 6.2 il y a un opérateur similaire

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

re: "nous aimerions être en mesure de faire correspondre sur bla bla foo bar foo? bar? foo * bar? et d'autres templates complexes." Je n'ai pas réellement essayé ceci (n'ai pas encore eu besoin), mais avez-vous essayé using System.Text.RegularExpressions.RegEx?

Vous pouvez utiliser un réel comme dans Lien aux entités assez facilement

Ajouter

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

à votre EDMX dans cette balise:

edmx: Edmx / edmx: Exécution / edmx: ConceptualModels / Schema

Souvenez-vous également de l'espace de noms dans l'atsortingbut <schema namespace="" />

Ajoutez ensuite une class d'extension dans l'espace de noms ci-dessus:

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

Cette méthode d'extension va maintenant correspondre à la fonction EDMX.

Plus d'infos ici: http://jendaperl.blogspot.be/2011/02/like-in-linq-to-entities.html