باستخدام يحتوي على () في LINQ إلى SQL
-
24-09-2019 - |
سؤال
أحاول تنفيذ البحث عن الكلمات الأساسية الأساسية في تطبيق باستخدام 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;
}
إنها ليست جميلة ، لكنها يجب أن تعمل. ستحصل على استعلام مع الكثير من AND
S في الفقرة حيث.
يمكنك كتابته بهذا
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;
}