문자열 필드가있는 엔터티에 대해 Entity Framework에서 “LIKE”연산자를 구현하려고하지만 지원되지 않는 것 같습니다. 다른 사람이 이와 같은 작업을 시도한 적이 있습니까?
이 블로그 게시물 은 우리가 겪고있는 문제를 요약합니다. contains를 사용할 수 있지만 LIKE의 가장 사소한 경우에만 일치합니다. contains, startswith, endswith 및 indexof를 결합하면 표준 와일드 카드와 Linq를 엔티티 코드로 변환해야합니다.
답변
이것은 현재 오래된 게시물이지만 답변을 찾는 사람에게는 이 링크 가 도움이 될 것입니다. 이미 EF 6.2.x를 사용중인 경우이 답변으로 이동하십시오 . 에 이 답변 당신은 EF 코어 2.X를 사용하는 경우
짧은 버전 :
SqlFunctions.PatIndex 메서드-모든 유효한 텍스트 및 문자 데이터 형식에서 지정된 식에서 패턴이 처음 나타나는 시작 위치를 반환하거나 패턴이없는 경우 0을 반환합니다.
네임 스페이스 : 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를 기반으로 클라이언트 측 Wildcard / Regex 필터링을 사용했습니다 . 간단하고 다음과 같이 작동합니다. 예상됩니다.
이 주제에 대한 또 다른 토론을 찾았습니다. 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);
참고 :이 솔루션은 비표준 PATINDEX 함수를 사용하기 때문에 SQL-Server 전용입니다.
답변
업데이트 : EF 6.2에는 like 연산자가 있습니다.
Where(obj => DbFunctions.Like(obj.Column , "%expression%")
답변
거기에 LIKE
운영자가 추가됩니다 Entity Framework Core 2.0
:
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
답변
특히 Entity 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을 사용하는 경우 와일드 카드 검색을 위해 % 문자를 지원하는 두 가지 확장 메서드를 작성했습니다. (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 ‘