سؤال

أحاول تنفيذ البحث عن الكلمات الأساسية الأساسية في تطبيق باستخدام LINQ إلى SQL. توجد مصطلحات البحث الخاصة بي في مجموعة من الأوتار ، كل عنصر صفيف هو كلمة واحدة ، وأود أن أجد الصفوف التي تحتوي على مصطلحات البحث. لا أمانع إذا كانت تحتوي على أكثر من مجرد مصطلحات البحث (على الأرجح ، سيفعلون) ، ولكن يجب أن تكون جميع مصطلحات البحث موجودة.

من الناحية المثالية ، أود شيء مشابه للمقتطف أدناه ، لكنني أعلم أن هذا لن ينجح. أيضا ، لقد نظرت إلى هذا السؤال هنا, ، لكن مؤلف هذا السؤال يبدو راضيا عن القيام بالأشياء في الاتجاه الآخر ( query.Contains(part.partName) ) ، والتي لا تعمل بالنسبة لي.

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

كيف يمكنني إعادة كتابة هذا الاستعلام حتى يفعل ما أحتاجه؟

هل كانت مفيدة؟

المحلول

النظر إلى المحاولات الأخرى يحزنني :(

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

الافتراضات:

  • يشبه Partname: "ABC 123 XYZ"

  • الاستعلام هو {"ABC" ، "123" ، "XY"}

نصائح أخرى

حل أبسط وصحيح (ثم ليبي):

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

هذا سوف يعمل طالما partName هي سلسلة (أو مكافئ SQL لسلسلة).

الشيء المهم الذي يجب ملاحظته هو partName.Contains(qs) يختلف عن query.Contains(partName).
مع partName.Contains(qs), partName يتم تفتيشه عن أي حدوث qs. سيكون SQL الناتج مكافئًا (حيثu003Cqs> هي قيمة qs):

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

من الجدير بالملاحظة StartsWith و EndsWith التي تشبه Contains ولكن ابحث عن السلسلة في الموقع المحدد.

query.Contains(partName) هو نفس SQL in أمر. سيكون SQL الناتج مكافئًا لـ (حيثu003Cquery0> هي قيمة query[0], بu003Cquery1> هي قيمة query[1], ، وu003CqueryN> هي القيمة الأخيرة في صفيف الاستعلام):

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

تحديث:
من المهم أيضًا ملاحظة أن إجابة Leppie لا تفلت من شخصيات البدل قبل إضافتها إلى مثل بيان. هذه ليست مشكلة في Contains الحل منذ أن هرب LINQ من الاستعلام قبل إرساله. نسخة هربت من SqlMethods.Like سيكون الحل:

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

لا داعي للقلق بشأن "لأن LINQ سوف يهرب من أجلك.

بامكانك ان تحاول:

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

ومع ذلك ، لست متأكدًا مما إذا كان LINQ to SQL قادرًا على تحويله إلى T-SQL. خيار آخر سيكون:

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

إنها ليست جميلة ، لكنها يجب أن تعمل. ستحصل على استعلام مع الكثير من ANDS في الفقرة حيث.

يمكنك كتابته بهذا

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

باستخدام Ninjanye.SearchExtension تتيح لك حزمة Nuget إجراء هذا البحث بسهولة:

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

يمكنك أيضًا البحث عن خصائص سلسلة متعددة

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

أو أداء RankedSearch الذي يعود IQueryable<IRanked<T>> الذي يتضمن ببساطة خاصية توضح عدد المرات التي ظهرت فيها مصطلحات البحث:

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

يوجد دليل أكثر شمولاً في صفحة GitHub Projects: https://github.com/ninjanye/searchextensions

آمل أن يساعد هذا الزوار في المستقبل

أشعر أن هذا بسيط إلى حد ما ويعمل بالنسبة لي:

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

الرجاء جرب هذا:

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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top