เรากำลังดำเนินการเกี่ยวกับ Log Viewer การใช้งานจะมีตัวเลือกในการกรองตามผู้ใช้ความรุนแรงและอื่น ๆ ในวันที่ Sql ฉันจะเพิ่มสตริงการสืบค้น แต่ฉันต้องการทำด้วย Linq ฉันจะเพิ่ม where-clauses ตามเงื่อนไขได้อย่างไร
เรากำลังดำเนินการเกี่ยวกับ Log Viewer การใช้งานจะมีตัวเลือกในการกรองตามผู้ใช้ความรุนแรงและอื่น ๆ ในวันที่ Sql ฉันจะเพิ่มสตริงการสืบค้น แต่ฉันต้องการทำด้วย Linq ฉันจะเพิ่ม where-clauses ตามเงื่อนไขได้อย่างไร
คำตอบ:
หากคุณต้องการกรองเฉพาะเมื่อผ่านเกณฑ์บางอย่างให้ทำสิ่งนี้
var logs = from log in context.Logs
select log;
if (filterBySeverity)
logs = logs.Where(p => p.Severity == severity);
if (filterByUser)
logs = logs.Where(p => p.User == user);
การทำเช่นนี้จะทำให้ Expression tree ของคุณตรงตามที่คุณต้องการ ด้วยวิธีนี้ SQL ที่สร้างขึ้นจะเป็นสิ่งที่คุณต้องการและไม่มีอะไรน้อย
LINQ to Entities does not recognize the method 'System.String get_Item(System.String)' method, and this method cannot be translated into a store expression.
หากคุณต้องการกรองฐานใน List / Array ให้ใช้สิ่งต่อไปนี้:
public List<Data> GetData(List<string> Numbers, List<string> Letters)
{
if (Numbers == null)
Numbers = new List<string>();
if (Letters == null)
Letters = new List<string>();
var q = from d in database.table
where (Numbers.Count == 0 || Numbers.Contains(d.Number))
where (Letters.Count == 0 || Letters.Contains(d.Letter))
select new Data
{
Number = d.Number,
Letter = d.Letter,
};
return q.ToList();
}
ฉันจบลงด้วยคำตอบที่คล้ายกับของ Daren แต่มีอินเทอร์เฟซ IQueryable:
IQueryable<Log> matches = m_Locator.Logs;
// Users filter
if (usersFilter)
matches = matches.Where(l => l.UserName == comboBoxUsers.Text);
// Severity filter
if (severityFilter)
matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);
Logs = (from log in matches
orderby log.EventTime descending
select log).ToList();
ที่สร้างแบบสอบถามก่อนที่จะกดฐานข้อมูล คำสั่งจะไม่ทำงานจนกว่า. toList () ในตอนท้าย
เมื่อพูดถึง linq แบบมีเงื่อนไขฉันชอบฟิลเตอร์และรูปแบบท่อมาก
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/
โดยทั่วไปคุณจะสร้างวิธีการขยายสำหรับแต่ละกรณีตัวกรองที่ใช้ใน IQueryable และพารามิเตอร์
public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}
ฉันแก้ไขสิ่งนี้ด้วยวิธีการขยายเพื่ออนุญาตให้ LINQ เปิดใช้งานตามเงื่อนไขกลางนิพจน์ที่คล่องแคล่ว สิ่งนี้ทำให้ไม่จำเป็นต้องแยกนิพจน์ด้วยif
คำสั่ง
.If()
วิธีการขยาย:
public static IQueryable<TSource> If<TSource>(
this IQueryable<TSource> source,
bool condition,
Func<IQueryable<TSource>, IQueryable<TSource>> branch)
{
return condition ? branch(source) : source;
}
สิ่งนี้ช่วยให้คุณทำสิ่งนี้:
return context.Logs
.If(filterBySeverity, q => q.Where(p => p.Severity == severity))
.If(filterByUser, q => q.Where(p => p.User == user))
.ToList();
นี่คือIEnumerable<T>
เวอร์ชันที่จะจัดการกับนิพจน์ LINQ อื่น ๆ ส่วนใหญ่:
public static IEnumerable<TSource> If<TSource>(
this IEnumerable<TSource> source,
bool condition,
Func<IEnumerable<TSource>, IEnumerable<TSource>> branch)
{
return condition ? branch(source) : source;
}
อีกตัวเลือกหนึ่งที่จะใช้สิ่งที่ต้องการ PredicateBuilder กล่าวถึงที่นี่ ช่วยให้คุณสามารถเขียนโค้ดดังต่อไปนี้:
var newKids = Product.ContainsInDescription ("BlackBerry", "iPhone");
var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
.And (Product.IsSelling());
var query = from p in Data.Products.Where (newKids.Or (classics))
select p;
โปรดทราบว่าฉันมีเพียงสิ่งนี้เพื่อทำงานกับ Linq 2 SQL EntityFramework ไม่ได้ใช้ Expression.Invoke ซึ่งจำเป็นสำหรับวิธีนี้ในการทำงาน ฉันมีคำถามเกี่ยวกับเรื่องนี้ที่นี่
ทำสิ่งนี้:
bool lastNameSearch = true/false; // depending if they want to search by last name,
มีสิ่งนี้ในwhere
คำสั่ง:
where (lastNameSearch && name.LastNameSearch == "smith")
หมายความว่าเมื่อมีการสร้างแบบสอบถามสุดท้ายหากlastNameSearch
เป็นfalse
แบบสอบถามจะละเว้น SQL ทั้งหมดสำหรับการค้นหานามสกุล
ไม่ใช่สิ่งที่สวยที่สุด แต่คุณสามารถใช้นิพจน์แลมบ์ดาและส่งผ่านเงื่อนไขของคุณได้ ใน TSQL ฉันทำสิ่งต่อไปนี้มากมายเพื่อให้พารามิเตอร์เป็นทางเลือก:
WHERE Field = @FieldVar หรือ @FieldVar เป็นโมฆะ
คุณสามารถทำซ้ำสไตล์เดียวกันด้วยแลมด้าต่อไปนี้ (ตัวอย่างการตรวจสอบการพิสูจน์ตัวตน):
MyDataContext db = MyDataContext ใหม่ ();
เป็นโมฆะ RunQuery (สตริง param1, สตริง param2, int? param3) {
Func checkUser = ผู้ใช้ =>
((param1.Length> 0)? user.Param1 == param1: 1 == 1) &&
((param2.Length> 0)? user.Param2 == param2: 1 == 1) &&
((param3! = null)? user.Param3 == param3: 1 == 1);
ผู้ใช้ foundUser = db.Users.SingleOrDefault (checkUser);
}
เมื่อเร็ว ๆ นี้ฉันมีข้อกำหนดที่คล้ายกันและในที่สุดก็พบสิ่งนี้ใน MSDN CSharp ตัวอย่างสำหรับ Visual Studio 2008
คลาสที่รวมอยู่ในตัวอย่าง DynamicQuery ของการดาวน์โหลดช่วยให้คุณสร้างแบบสอบถามแบบไดนามิกที่รันไทม์ในรูปแบบต่อไปนี้:
var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");
การใช้สิ่งนี้คุณสามารถสร้างสตริงการสืบค้นแบบไดนามิกที่รันไทม์และส่งผ่านไปยังเมธอด Where ():
string dynamicQueryString = "City = \"London\" and Order.Count >= 10";
var q = from c in db.Customers.Where(queryString, null)
orderby c.CompanyName
select c;
คุณสามารถสร้างและใช้วิธีการขยายนี้
public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool isToExecute, Expression<Func<TSource, bool>> predicate)
{
return isToExecute ? source.Where(predicate) : source;
}
เพียงใช้ตัวดำเนินการ && ของ C #:
var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical")
แก้ไข: อาต้องอ่านอย่างละเอียดมากขึ้น ที่คุณอยากรู้วิธีการเงื่อนไขเพิ่มคำสั่งเพิ่มเติม ในกรณีนั้นฉันไม่รู้ :) สิ่งที่ฉันควรทำก็แค่เตรียมแบบสอบถามหลาย ๆ ข้อและดำเนินการให้ถูกต้องขึ้นอยู่กับสิ่งที่ฉันต้องการ
คุณสามารถใช้วิธีการภายนอก:
var results =
from rec in GetSomeRecs()
where ConditionalCheck(rec)
select rec;
...
bool ConditionalCheck( typeofRec input ) {
...
}
สิ่งนี้ใช้ได้ แต่ไม่สามารถแบ่งออกเป็นแผนภูมินิพจน์ได้ซึ่งหมายความว่า Linq to SQL จะรันโค้ดตรวจสอบกับทุกระเบียน
อีกทางหนึ่ง:
var results =
from rec in GetSomeRecs()
where
(!filterBySeverity || rec.Severity == severity) &&
(!filterByUser|| rec.User == user)
select rec;
สิ่งนี้อาจใช้ได้ในแผนภูมินิพจน์ซึ่งหมายความว่า Linq เป็น SQL จะได้รับการปรับให้เหมาะสม
สิ่งที่ฉันคิดคือคุณสามารถใส่เงื่อนไขการกรองลงในรายการทั่วไปของ Predicates:
var list = new List<string> { "me", "you", "meyou", "mow" };
var predicates = new List<Predicate<string>>();
predicates.Add(i => i.Contains("me"));
predicates.Add(i => i.EndsWith("w"));
var results = new List<string>();
foreach (var p in predicates)
results.AddRange(from i in list where p.Invoke(i) select i);
ซึ่งส่งผลให้รายการมี "ฉัน" "ฉัน" และ "ตัดหญ้า"
คุณสามารถปรับให้เหมาะสมได้โดยทำ foreach กับเพรดิเคตในฟังก์ชันที่แตกต่างกันโดยสิ้นเชิงที่ ORs เพรดิเคต