ใน T-SQL คุณสามารถมีแบบสอบถามเช่น:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
คุณจะทำซ้ำสิ่งนั้นในการสืบค้น LINQ ไปยังนิติบุคคล? เป็นไปได้ไหม
ใน T-SQL คุณสามารถมีแบบสอบถามเช่น:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
คุณจะทำซ้ำสิ่งนั้นในการสืบค้น LINQ ไปยังนิติบุคคล? เป็นไปได้ไหม
คำตอบ:
คุณต้องเปิดมันไว้ในหัวของวิธีที่คุณคิดเกี่ยวกับมัน แทนที่จะทำ "ใน" เพื่อค้นหาสิทธิ์ผู้ใช้ของรายการปัจจุบันในชุดสิทธิ์ผู้ใช้ที่กำหนดไว้ล่วงหน้าคุณกำลังขอสิทธิ์ผู้ใช้ชุดที่กำหนดไว้ล่วงหน้าหากมีค่าที่เกี่ยวข้องของรายการปัจจุบัน นี่เป็นวิธีเดียวกับที่คุณจะพบรายการในรายการปกติใน. NET
มีสองวิธีในการทำสิ่งนี้โดยใช้ LINQ วิธีหนึ่งใช้ไวยากรณ์คิวรีและอีกวิธีใช้ไวยากรณ์เมธอด โดยพื้นฐานแล้วพวกมันเหมือนกันและสามารถใช้แทนกันได้ขึ้นอยู่กับความต้องการของคุณ:
ไวยากรณ์การสืบค้น:
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
ไวยากรณ์ของวิธีการ:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
การตั้งค่าส่วนบุคคลของฉันในกรณีนี้อาจเป็นวิธีการไวยากรณ์เพราะแทนที่จะกำหนดตัวแปรฉันสามารถ foreach ผ่านสายที่ไม่ระบุชื่อเช่นนี้:
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
วากยสัมพันธ์นี่ดูซับซ้อนมากขึ้นและคุณต้องเข้าใจแนวคิดของแลมบ์ดานิพจน์หรือผู้ได้รับมอบหมายเพื่อให้เข้าใจว่าเกิดอะไรขึ้นจริง ๆ แต่อย่างที่คุณเห็นนี่ทำให้รหัสมีความเป็นธรรม
ทุกอย่างลงมาในรูปแบบการเข้ารหัสและความชอบของคุณตัวอย่างทั้งสามของฉันทำสิ่งเดียวกันแตกต่างกันเล็กน้อย
อีกวิธีหนึ่งที่ไม่ได้ใช้ LINQ คุณสามารถใช้ไวยากรณ์ของวิธีการเดิมแทน "ที่ไหน" กับ "FindAll" และรับผลลัพธ์เดียวกันซึ่งจะทำงานใน NET 2.0:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
สิ่งนี้จะเพียงพอต่อความต้องการของคุณ มันเปรียบเทียบสองคอลเลกชันและตรวจสอบว่าคอลเลกชันหนึ่งมีค่าที่ตรงกับที่อยู่ในคอลเลกชันอื่น ๆ
fea_Features.Where(s => selectedFeatures.Contains(s.feaId))
หากคุณใช้ VS2008 / .net 3.5 ดูคำแนะนำของ Alex James # 8: http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style -queries โดยใช้-LINQ เพื่อ entities.aspx
มิฉะนั้นก็ใช้วิธี array.Contains (someEntity.Member)
ฉันจะไปเข้าร่วมวงในในบริบทนี้ ถ้าฉันจะใช้ประกอบด้วยมันจะย้ำ 6 ครั้งแม้จะมีความจริงที่ว่ามีเพียงหนึ่งการแข่งขัน
var desiredNames = new[] { "Pankaj", "Garg" };
var people = new[]
{
new { FirstName="Pankaj", Surname="Garg" },
new { FirstName="Marc", Surname="Gravell" },
new { FirstName="Jeff", Surname="Atwood" }
};
var records = (from p in people join filtered in desiredNames on p.FirstName equals filtered select p.FirstName).ToList();
สมมติว่าฉันมีวัตถุสองรายการ
List 1 List 2
1 12
2 7
3 8
4 98
5 9
6 10
7 6
การใช้ประกอบด้วยจะค้นหาแต่ละรายการ 1 รายการในรายการ 2 ซึ่งหมายความว่าการทำซ้ำจะเกิดขึ้น 49 ครั้ง !!!
นี่อาจเป็นวิธีที่เป็นไปได้ที่คุณสามารถใช้วิธีการขยาย LINQ โดยตรงเพื่อตรวจสอบข้อใน
var result = _db.Companies.Where(c => _db.CurrentSessionVariableDetails.Select(s => s.CompanyId).Contains(c.Id)).ToList();
ฉันยังพยายามที่จะทำงานกับ SQL-IN-เหมือนสิ่ง - สอบถามกับข้อมูลนิติบุคคลรุ่น วิธีการของฉันคือเครื่องมือสร้างสตริงเพื่อเขียน OR-expression ขนาดใหญ่ นั่นน่าเกลียดมาก แต่ฉันเกรงว่ามันเป็นวิธีเดียวที่จะไปในตอนนี้
ตอนนี้ดูเหมือนว่า:
Queue<Guid> productIds = new Queue<Guid>(Products.Select(p => p.Key));
if(productIds.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.ProductId = Guid\'{1}\'", entities.Products.Name, productIds.Dequeue());
while(productIds.Count > 0)
{
sb.AppendFormat(" OR {0}.ProductId = Guid\'{1}\'",
entities.Products.Name, productIds.Dequeue());
}
}
การทำงานกับ GUID ในบริบทนี้ : ตามที่คุณเห็นด้านบนจะมีคำว่า "GUID" อยู่ข้างหน้า GUID ถ้าตัวเองอยู่ในแฟรกเมนต์สตริงการสืบค้น หากคุณไม่เพิ่มสิ่งนี้ให้ObjectQuery<T>.Where
โยนข้อยกเว้นต่อไปนี้:
อาร์กิวเมนต์ชนิด 'Edm.Guid' และ 'Edm.String' ไม่เข้ากันสำหรับการดำเนินการนี้ใกล้กับนิพจน์เท่ากับบรรทัด 6 คอลัมน์ 14
พบสิ่งนี้ในฟอรัม MSDN อาจเป็นประโยชน์หากมีอยู่ในใจ
มัทธีอัส
... รอคอยรุ่นต่อไปของ. NET และ Entity Framework เมื่อทุกอย่างดีขึ้น :)
วิธีอื่นในการตอบ BenAlabaster
ก่อนอื่นคุณสามารถเขียนแบบสอบถามแบบนี้ใหม่:
var matches = from Users in people
where Users.User_Rights == "Admin" ||
Users.User_Rights == "Users" ||
Users.User_Rights == "Limited"
select Users;
แน่นอนว่านี่เป็น 'คำพูด' มากกว่าและความเจ็บปวดในการเขียน แต่มันก็ใช้งานได้เหมือนกันทั้งหมด
ดังนั้นถ้าเรามีวิธีอรรถประโยชน์ที่ทำให้มันง่ายในการสร้างการแสดงออกของ LINQ เหล่านี้เราจะอยู่ในธุรกิจ
ด้วยวิธีการใช้งานยูทิลิตี้คุณสามารถเขียนสิ่งนี้:
var matches = ctx.People.Where(
BuildOrExpression<People, string>(
p => p.User_Rights, names
)
);
สิ่งนี้จะสร้างนิพจน์ที่มีผลเหมือนกับ:
var matches = from p in ctx.People
where names.Contains(p.User_Rights)
select p;
แต่ที่สำคัญกว่านั้นใช้งานได้กับ. NET 3.5 SP1
นี่คือฟังก์ชั่นระบบประปาที่ทำให้สิ่งนี้เป็นไปได้:
public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(
Expression<Func<TElement, TValue>> valueSelector,
IEnumerable<TValue> values
)
{
if (null == valueSelector)
throw new ArgumentNullException("valueSelector");
if (null == values)
throw new ArgumentNullException("values");
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
return e => false;
var equals = values.Select(value =>
(Expression)Expression.Equal(
valueSelector.Body,
Expression.Constant(
value,
typeof(TValue)
)
)
);
var body = equals.Aggregate<Expression>(
(accumulate, equal) => Expression.Or(accumulate, equal)
);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
ฉันจะไม่พยายามอธิบายวิธีการนี้นอกจากจะบอกว่ามันเป็นการสร้างนิพจน์เพรดิเคตสำหรับค่าทั้งหมดโดยใช้ valueSelector (เช่น p => p.User_Rights) และ ORs เพรดิเคตด้วยกันเพื่อสร้างนิพจน์ที่สมบูรณ์ คำกริยา
ตัวอย่างจริง:
var trackList = Model.TrackingHistory.GroupBy(x => x.ShipmentStatusId).Select(x => x.Last()).Reverse();
List<int> done_step1 = new List<int>() {2,3,4,5,6,7,8,9,10,11,14,18,21,22,23,24,25,26 };
bool isExists = trackList.Where(x => done_step1.Contains(x.ShipmentStatusId.Value)).FirstOrDefault() != null;
อย่างจริงจัง? คนที่คุณไม่เคยใช้
where (t.MyTableId == 1 || t.MyTableId == 2 || t.MyTableId == 3)
Checks = NumValues * NumRows
เช่นเดียวกันกับจำนวนของค่าที่เป็นไปได้: เนื่องจากนี่เป็นการคำนวณประเภท M * N หากมีขนาดเล็กดังนั้นเวลาที่ใช้ในการตรวจสอบแต่ละครั้งก็จะมีค่าน้อยเช่นกัน ฉันเพิ่มข้อ จำกัด เพื่อให้ cjm30305 รู้วิธีตั้งค่าสภาพแวดล้อมการทดสอบซึ่งแสดงว่าทำไมโซลูชันของเขาจึงไม่ดี
where new[] { 1, 2, 3 }.Contains(x)
มันเปรียบเทียบน้อยกว่าwhere (x == 1 || x == 2 || x == 3)
หรือเปล่า?