Frage

mit Linq-to-SQL

Ich versuche, eine sehr einfache Stichwortsuche in einer Anwendung zu implementieren. Meine Suchbegriffe sind in einer Reihe von Strings, wobei jedes Array-Element ein Wort zu sein, und ich möchte die Zeilen finden, die die Suchbegriffe enthalten. Ich habe nichts dagegen, wenn sie mehr als nur die Suchbegriffe enthalten (wahrscheinlich, sie werden), aber alle die Suchbegriffe vorhanden sein müssen.

Im Idealfall würde ich etwas ähnliches wie die Schnipsel wie unten, aber ich weiß, dass dies nicht funktioniert. Außerdem habe ich sah diese Frage hier , aber der Autor dieser Frage scheint Inhalt Dinge umgekehrt (query.Contains(part.partName)) zu tun, was für mich nicht funktioniert.

public IQueryable<Part> SearchForParts(string[] query)
{
    return from part in db.Parts
           where part.partName.Contains(query)
           select part;
}

Wie kann ich diese Abfrage neu zu schreiben, so dass es das tun, was ich brauche?

War es hilfreich?

Lösung

Mit Blick auf die anderen Versuche, macht mich traurig: (

public IQueryable<Part> SearchForParts(string[] query)
{
  var q = db.Parts.AsQueryable(); 

  foreach (var qs in query)
  { 
    var likestr = string.Format("%{0}%", qs);
    q = q.Where(x => SqlMethods.Like(x.partName, likestr));
  }

  return q;
}

Annahmen:

  • partname sieht aus wie: "ABC 123 XYZ"

  • Abfrage { "ABC", "123", "XY"}

Andere Tipps

Eine einfachere und korrekte Lösung (dann leppie ist):

public IQueryable<Part> SearchForParts(string[] query)
{
    var q = db.Parts.AsQueryable(); 

    foreach (string qs in query)
    {
        q = q.Where(x => x.partName.Contains(qs));
    }

    return q;
}

Das funktioniert solange partName ist eine Zeichenkette (oder eine SQL-Äquivalent einer Zeichenkette).

Die wichtige Sache zu beachten ist partName.Contains(qs) ist anders als query.Contains(partName) .
Mit partName.Contains(qs) wird partName für das Auftreten von qs gesucht. Die sich ergebende SQL wäre Äquivalent (wobei ist der Wert von qs):

select * from Parts where partName like '%<qs>%';

Bemerkenswert sind auch StartsWith und EndsWith , die ähnlich Contains aber sucht die Zeichenfolge in der bestimmten Stelle.

query.Contains(partName) ist das gleiche wie ein SQL in Befehl. Die sich ergebende SQL äquivalent sein würde (wobei der Wert query[0] ist, ist der Wert von query[1] und ist der letzte Wert in der Abfrage-Array):

select * from Parts where partName in ( <query0>, <query1>, ..., <queryN> );

Update:
Es ist auch wichtig Antwort zu beachten, dass leppie die nicht die Platzhalter nicht entkommen, bevor sie auf die wie Aussage. Dies ist nicht ein Problem mit der Contains Lösung, da Linq die Abfrage entkommen vor dem Senden. Eine maskierte Version der SqlMethods.Like Lösung wäre:

public IQueryable<Part> SearchForParts(string[] query)
{
    var q = db.Parts.AsQueryable(); 

    foreach (var qs in query)
    {
        string escaped_bs = qs.Replace("/", "//"),
            escaped_us = escaped_bs.Replace("_", "/_"),
            escaped_p = escaped_us.Replace("%", "/%"),
            escaped_br = escaped_p.Replace("[", "/["),
            likestr = string.Format("%{0}%", escaped_br);

        q = q.Where(x => SqlMethods.Like(x.partName, likestr, '/'));
    }

    return q;
}

Sie haben keine Sorgen zu machen ", da Linq, dass für Sie entkommen.

Sie könnten versuchen:

public IQueryable<Part> SearchForParts(string[] query)
{
    return from part in db.Parts
           where query.All(term => part.partName.Contains(term))
           select part;
}

Aber ich bin nicht sicher, ob LINQ to SQL in der Lage, sie in T-SQL zu transformieren. Eine andere Möglichkeit wäre:

public IQueryable<Part> SearchForParts(string[] query)
{
    var result = from part in db.Parts
                 select part;

    foreach(var term in query)
    {
        result = from part in result
                 where part.partName.Contains(term)
                 select part;
    }

    return result;
}

Es ist nicht so schön, aber es sollte funktionieren. Sie erhalten eine Abfrage mit vielen ANDs in dem where-Klausel erhalten.

Sie können es als dieser

schreiben
var result = db.Parts.Where(p => query.All(q => p.partName.Contains(q)));

, um die Verwendung von NinjaNye.SearchExtension nuget Paket ermöglicht es Ihnen, diese Suche mit Leichtigkeit auszuführen:

string[] terms = new[]{"search", "term", "collection"};
var result = db.Parts.Search(terms, p => p.PartName);

Sie können auch mehrere String-Eigenschaften

suchen
var result = db.Parts.Search(terms, p => p.PartName, p.PartDescription);

oder ein RankedSearch durchführen, die IQueryable<IRanked<T>> gibt, die einfach eine Eigenschaft enthält, die zeigt, wie viele Male der Suchbegriffe erschienen:

//Perform search and rank results by the most hits
var result = db.Parts.RankedSearch(terms, p => p.PartName, p.PartDescription)
                     .OrderByDescending(r = r.Hits);

Es ist ein umfangreicher Leitfaden zu den Projekten GitHub Seite: https://github.com/ninjanye/SearchExtensions

Hope, das hilft zukünftige Besucher

Ich fühle mich ist dies etwas einfach und für mich arbeiten:

string[] product = products.Split(','); 
using (var context = new ProjectTrackerEntities()) 
{ var result = from part in context.DBAudits where product.Contains(part.TableName) select part; }

Bitte versuchen Sie dies:

public IQueryable<Part> SearchForParts(string[] query)
{
    return from part in db.Parts
           where Search(part.Name,query)
           select part;
}

public bool Search(string partName,string[] query)
{
    for (int i = 0; i < query.Length; i++)
    {
        if(partName.Contains(query[i]))
           return true;
    }

    return false;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top