像entity framework中的运算符一样?
我们试图在entity framework中为string字段的实体实现“LIKE”运算符,但似乎并不支持。 有没有人试图做这样的事情?
这篇博文总结了我们遇到的问题。 我们可以使用contains,但是只匹配LIKE的最简单的情况。 合并contains,startswith,endswith和indexof让我们在那里,但需要标准通配符和Linq到实体代码之间的转换。
这是一个旧post,但对于任何寻找答案的人来说,这个链接应该有所帮助:
http://msdn.microsoft.com/en-us/library/system.data.objects.sqlclient.sqlfunctions.patindex.aspx
SqlFunctions.PatIndex方法 – 返回指定expression式中模式第一次出现的起始位置,如果找不到模式,则返回所有有效文本和字符数据types的零
命名空间:System.Data.Objects.SqlClient程序集:System.Data.Entity(在System.Data.Entity.dll中)
有一个解释出现在这个论坛主题:
我真的不知道EF的任何内容,但在LINQ to SQL中,通常使用String.Contains表示一个LIKE子句:
where entity.Name.Contains("xyz")
翻译成
WHERE Name LIKE '%xyz%'
(使用StartsWith
和EndsWith
作其他行为。)
我不完全确定这是否有帮助,因为我不明白当你说要实现 LIKE时你的意思。 如果我完全误解了,让我知道,我会删除这个答案:)
我有同样的问题。
现在,我已经解决了基于http://www.codeproject.com/Articles/11556/Converting-Wildcards-to-Regexes?msg=1423024#xx1423024xx的客户端通配符/正则expression式过滤; – 它很简单,作为预期。
我已经find关于这个主题的另一个讨论: http : //forums.asp.net/t/1654093.aspx/2/10
这篇文章看起来很有希望,如果你使用entity framework> = 4.0:
使用SqlFunctions.PatIndex:
http://msdn.microsoft.com/en-us/library/system.data.objects.sqlclient.sqlfunctions.patindex.aspx
喜欢这个:
var q = EFContext.Products.Where(x => SqlFunctions.PatIndex("%CD%BLUE%", x.ProductName) > 0);
注意:这个解决scheme只适用于SQL-Server,因为它使用非标准的PATINDEX函数。
在文档中特别提到它是实体SQL的一部分。 你是否收到错误信息?
// 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%'
如果你使用的是MS Sql,我写了两个扩展方法来支持通配符search的%字符。 (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; } }
用法
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();
在ef6中,它应该转化为
.... 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'
在Entity Framework Core 2.0
添加了LIKE
操作符:
var query = from e in _context.Employees where EF.Functions.Like(e.Title, "%developer%") select e;
比较... where e.Title.Contains("developer") ...
它真的被翻译成SQL
LIKE
而不是CHARINDEX
我们看到的Contains
方法。
回答:“我们希望能够匹配blah foo bar foo?bar?foo * bar?和其他复杂模式。” 我还没有真正尝试过(尚不需要),但你有没有尝试过使用System.Text.RegularExpressions.RegEx?
你可以很容易的使用实体链接
加
<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>
到你的EDMX在这个标签:
EDMX:EDMX / EDMX:运行/ EDMX:ConceptualModels /架构
还要记住<schema namespace="" />
属性中的<schema namespace="" />
然后在上面的命名空间中添加一个扩展类:
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"); } }
这个扩展方法现在将映射到EDMXfunction。
更多信息: http : //jendaperl.blogspot.be/2011/02/like-in-linq-to-entities.html