programing

운영자처럼요?

showcode 2023. 4. 25. 23:46
반응형

운영자처럼요?

문자열 필드가 있는 엔티티에 대해 Entity Framework에서 "LIKE" 연산자를 구현하려고 하지만 지원되지 않는 것 같습니다.또 이런 시도를 한 사람이 있나요?

이 블로그 게시물은 우리가 안고 있는 문제를 요약한 것입니다.포함을 사용할 수 있지만 LIKE의 경우 가장 사소한 경우에만 일치합니다.contains, startswith, endswith 및 indexof를 조합하면 이러한 결과를 얻을 수 있지만 표준 와일드카드와 Linq를 Entities 코드로 변환해야 합니다.

저는 EF에 대해 잘 모르지만 LINQ to SQL에서는 보통 String을 사용하여 LIKE 절을 표현합니다.다음을 포함합니다.

where entity.Name.Contains("xyz")

으로 변환됩니다.

WHERE Name LIKE '%xyz%'

(쓰세요.StartsWith그리고요.EndsWith을 사용하세요.)

LIKE를 구현하려고 하는 것이 무슨 뜻인지 잘 모르겠습니다.제가 완전히 오해한 경우 알려주시면 이 답변을 삭제하겠습니다.

업데이트: EF 6.2에 유사한 연산자가 있습니다.

Where(obj => DbFunctions.Like(obj.Column , "%expression%"))

이 게시물은 오래된 게시물이지만, 이 링크를 통해 답을 찾을 수 있습니다.EF 6.2.x를 이미 사용 중인 경우 이 답변으로 이동하십시오.EF Core 2.x를 사용하는 경우 이 질문에 답하십시오.

짧은 버전입니다.

SqlFunctions입니다.PatIndex 메서드 - 모든 유효한 텍스트 및 문자 데이터 유형에서 지정한 식에서 패턴이 처음 나타나는 시작 위치를 반환하거나, 패턴을 찾을 수 없는 경우 0을 반환합니다.

이름 공간:시스템.Data.Objects입니다.SqlClient 어셈블리:시스템.Data.Entity(시스템에서).Data.Entity.dll)입니다.

포럼 스레드에도 약간의 설명이 나타납니다.

어어가 있습니다.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네, 그렇습니다.

저도 같은 문제가 있었어요.

지금은 http://www.codeproject.com/Articles/11556/Converting-Wildcards-to-Regexes?msg=1423024#xx1423024xx을 기반으로 한 클라이언트 측 와일드카드/Regex 필터링으로 해결했습니다. 단순하고 예상대로 작동합니다.

이 주제에 대한 또 다른 논의를 찾았습니다. http://forums.asp.net/t/1654093.aspx/2/10
엔티티 프레임워크 > = 4.0을 선택합니다.

SqlFunctions를 사용합니다.PatIndex: (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 전용입니다.

설명서에서 엔티티 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%'

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

다음은 EfCore의 LIKE 표현식을 구축하는 샘플입니다.

protected override Expression<Func<YourEntiry, bool>> BuildLikeExpression(string searchText)
    {
        var likeSearch = $"%{searchText}%";

        return t => EF.Functions.Like(t.Code, likeSearch)
                    || EF.Functions.Like(t.FirstName, likeSearch)
                    || EF.Functions.Like(t.LastName, likeSearch);
    }

//Calling method

var query = dbContext.Set<YourEntity>().Where(BuildLikeExpression("Text"));

MS SQL을 사용하는 경우 와일드카드 검색을 위해 % 문자를 지원하는 확장 메서드 2개를 작성했습니다(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%ello%', @p__linq_1 = '%Hi%', @p__linq_2 = '%Active'입니다.

엔티티 링크에서와 같은 real을 매우 쉽게 사용할 수 있습니다.

더하다

    <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:개념 모델/구성표입니다.

또한 의 네임스페이스도 기억하십시오.<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");
    }
}

이제 이 확장 방법이 EDMX 기능에 매핑됩니다.

자세한 내용은 http://jendaperl.blogspot.be/2011/02/like-in-linq-to-entities.html를 참조하십시오.

언급URL : https://stackoverflow.com/questions/1033007/like-operator-in-entity-framework 입니다.

반응형