Vind je operator in Entity Framework leuk?

We proberen de operator “LIKE” in Entity Framework te implementeren voor onze entiteiten met tekenreeksvelden, maar dit lijkt niet te worden ondersteund. Heeft iemand anders geprobeerd zoiets te doen?

Deze blogpostvat het samen het probleem dat we hebben. We zouden kunnen gebruiken bevat, maar dat komt alleen overeen met het meest triviale geval voor LIKE. Het combineren van bevat, begint met, eindigt met en indexof brengt ons daar, maar vereist een vertaling tussen standaard wildcards en Linq naar Entities-code.


Antwoord 1, autoriteit 100%

Ik weet eigenlijk niets over EF, maar in LINQ to SQL druk je meestal een LIKE-clausule uit met String.Contains:

where entity.Name.Contains("xyz")

vertaalt naar

WHERE Name LIKE '%xyz%'

(Gebruik StartsWithen EndsWithvoor ander gedrag.)

Ik weet niet helemaal zeker of dat nuttig is, want ik begrijp niet wat je bedoelt als je zegt dat je LIKE probeert te implementeren. Als ik het helemaal verkeerd heb begrepen, laat het me weten en ik verwijder dit antwoord 🙂


Antwoord 2, autoriteit 23%

Dit is nu een oud bericht, maar voor iedereen die op zoek is naar het antwoord, deze linkzou moeten helpen. Ga naar dit antwoordals je EF 6.2.x al gebruikt. Op dit antwoordals je EF Core 2.x gebruikt

Korte versie:

SqlFunctions.PatIndexmethode – retourneert de startpositie van het eerste exemplaar van een patroon in een opgegeven expressie, of nullen als het patroon niet wordt gevonden, op alle geldige tekst- en tekengegevenstypen

Naamruimte: System.Data.Objects.SqlClient
Assemblage: System.Data.Entity (in System.Data.Entity.dll)

Een beetje uitleg staat ook in deze forumthread.


Antwoord 3, autoriteit 22%

Ik had hetzelfde probleem.

Voorlopig heb ik genoegen genomen met Wildcard/Regex-filtering aan de clientzijde op basis van http://www.codeproject.com/Articles/11556/Converting-Wildcards-to-Regexes?msg=1423024#xx1423024xx– het is eenvoudig en werkt zoals verwacht.

Ik heb nog een discussie over dit onderwerp gevonden: http://forums. asp.net/t/1654093.aspx/2/10
Dit bericht ziet er veelbelovend uit als je Entity Framework >= 4.0 gebruikt:

Gebruik SqlFunctions.PatIndex:

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

Zoals dit:

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

Opmerking: deze oplossing is alleen voor SQL-Server, omdat het een niet-standaard PATINDEX-functie gebruikt.


Antwoord 4, autoriteit 22%

Update: In EF 6.2 is er een like-operator

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

Antwoord 5, autoriteit 21%

Er is een LIKE-operator toegevoegd in Entity Framework Core 2.0:

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

Vergeleken met ... where e.Title.Contains("developer") ...is het echt vertaald naar SQLLIKEin plaats van CHARINDEXzien we voor de methode Contains.


Antwoord 6, autoriteit 3%

Het wordt specifiek genoemd in de documentatie als onderdeel van Entity SQL. Krijgt u een foutmelding?

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


Antwoord 7

als je MS Sql gebruikt, heb ik 2 extensiemethoden geschreven om het %-teken voor zoeken met jokertekens te ondersteunen.
(LinqKit is vereist)

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;
    }
}

gebruik

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();    

in ef6 en het zou moeten vertalen naar

....
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’


Antwoord 8

Voor EfCore is hier een voorbeeld om LIKE-expressie te bouwen

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"));

Antwoord 9

Je kunt vrij gemakkelijk een echte like gebruiken in Link to Entities

Toevoegen

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

naar uw EDMX in deze tag:

edmx:Edmx/edmx:Runtime/edmx:ConceptualModels/Schema

Onthoud ook de naamruimte in het kenmerk <schema namespace="" />

Voeg vervolgens een extensieklasse toe in de bovenstaande naamruimte:

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");
    }
}

Deze uitbreidingsmethode wordt nu toegewezen aan de EDMX-functie.

Meer info hier: http://jendaperl. blogspot.be/2011/02/like-in-linq-to-entities.html

Other episodes