如何在LINQ to Entities中使用SQL’LIKE’?
我有一个文本框,允许用户指定搜索字符串,包括通配符,例如:
Joh* *Johnson *mit* *ack*on
在使用LINQ to Entities之前,我有一个存储过程,它将该字符串作为参数并执行:
SELECT * FROM Table WHERE Name LIKE @searchTerm
然后我会在传入之前执行String.Replace(’*’,’%’)。
现在有了LINQ to Entities,我正在尝试完成同样的事情。 我知道有StartsWith,EndsWith和Contains支持,但它不会以我需要的方式支持它。
我读到了“SqlMethods.Like”并尝试了这个:
var people = from t in entities.People where SqlMethods.Like(t.Name, searchTerm) select new { t.Name };
但是我得到以下exception:
LINQ to Entities does not recognize the method 'Boolean Like(System.String, System.String)' method, and this method cannot be translated into a store expression.
如何使用LINQ to Entities获得相同的function?
var people = entities.People.Where("it.Name LIKE @searchTerm", new ObjectParameter("searchTerm", searchTerm));
如何让它无缝地工作:
在您的EDMX模型中,添加:
searchingIn LIKE lookingFor
在开始的部分之后:
然后,在代码中的任何位置添加此扩展方法:
//prior to EF 6 [System.Data.Objects.DataClasses.EdmFunction("Your.Namespace", "String_Like")] //With EF 6 [System.Data.Entity.DbFunction("Your.Namespace", "String_Like")] public static bool Like(this string input, string pattern) { /* Turn "off" all regular expression related syntax in * the pattern string. */ pattern = Regex.Escape(pattern); /* Replace the SQL LIKE wildcard metacharacters with the * equivalent regular expression metacharacters. */ pattern = pattern.Replace("%", ".*?").Replace("_", "."); /* The previous call to Regex.Escape actually turned off * too many metacharacters, ie those which are recognized by * both the regular expression engine and the SQL LIKE * statement ([...] and [^...]). Those metacharacters have * to be manually unescaped here. */ pattern = pattern.Replace(@"\[", "[").Replace(@"\]", "]").Replace(@"\^", "^"); return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase); }
你有它。
现在你可以这样做:
(from e in Entities where e.Name like '%dfghj%' select e)
要么
string [] test = {"Sydney", "Melbourne", "adelaide", "ryde"}; test.Where(t=> t.Like("%yd%e%")).Dump();
那么,你的选择是:
- 使用
Contains
。 我知道你不喜欢它,但它可能会起作用。 - 从SqlFunctions中选择一个函数。 L2E都支持它们。
- 映射您自己的function 。
- ESQL为@Yury +1。
你可以这样做:
using System.Data.Entity; // EntityFramework.dll v4.3 var queryResult=db.Accounts.AsQueryable().Where(x => x.Name.Contains(queryKey));
因为Linq to Entity
无法将方法Contains()
转换为SQL,但Linq to SQL可以做到这一点。 我试图找到一个可以进行AsQueryable()
的方法,最后是AsQueryable()
,也是一个通用版本AsQueryable
。 在我的情况下,我发现我可以这样使用它,但它有任何副作用,我不知道,也许它会失去Entity
一些function。
解决方案是使用SQLFunctions.PatIndex
var result = from c in items where SqlFunctions.PatIndex(searchstring.ToLower(), c.fieldtoSearch) > 0 select c;
其中’searchstring’是搜索’fieldtoSearch’的模式,是要搜索的字段
Patindex()支持使用字符串模式搜索进行搜索。 搜索不区分大小写。
您可以像这样使用LINQ执行所有这些语句
string _search = "johnson"; // joh* OR joh% items.Where(i => i.Name.StartsWith(_search, StringComparison.OrdinalIgnoreCase)); // *son OR %son items.Where(i => i.Name.EndsWith(_search, StringComparison.OrdinalIgnoreCase)); // *hns* OR %hns% items.Where(i => i.Name.ToLower().Contains(_search));
var people = from t in entities.People where t.Name.ToLower().Contains(searchTerm.ToLower()) select new { t.Name };
编辑 – 我可能会混合语法。 我通常使用扩展方法; 但包含将工作。
过滤时不需要使用百分号。 例如;
如果我想检查ItemName不包含’ – ‘我将这样做
!Item.ItemName.Contains( “ – ”)
在SQL中,它将转换为NOT LIKE’% – %’
我们使用Database First和EntityFramework。
“映射你自己的function”。 方法与nuget EntityFramework.CodeFirstStoreFunctions一起为我们工作。
1步骤:在db中创建一个函数,如下所示:
CREATE FUNCTION [dbo].[StringLike] ( @a nvarchar(4000), @b nvarchar(4000) ) RETURNS bit AS BEGIN RETURN (SELECT CASE WHEN (SELECT 1 WHERE @a LIKE @b) = 1 THEN 1 ELSE 0 END) END
2步骤:安装nuget EntityFramework.CodeFirstStoreFunctions
3步骤:在代码中创建一个这样的方法(我在DbContext类中创建我的方法):
[DbFunction("CodeFirstDatabaseSchema", "StringLike")] public static bool Like(string input, string pattern) { throw new NotSupportedException("Direct calls are not supported."); }
4步骤:初始化EntityFramework.CodeFirstStoreFunctions。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Add(new FunctionsConvention("dbo", this.GetType())); }
5步骤:现在您可以在linq查询中使用此方法。
现在,EF支持“LIKE”用法,您可以使用所有sql通配符。 看一下这个。
var people = from t in entities.People select new { t.Name }; people = people.Where(x => DbFunctions.Like(x.Name, searchTerm));
通过以下方法很容易实现
var people = from t in entities.People where t.Name.Contains(searchTerm) select new { t.Name };
使用以下规范来实现通配符
LIKE 'a%' => StartsWith("a") LIKE '%a' => EndsWith("a") LIKE '%a%' => Contains("a") LIKE 'a%b' => StartsWith("a") && EndsWith("b") LIKE '%a%b%' => StartsWith("a") && Contains("b")