แปลงผลการค้นหา Linq เป็นพจนานุกรม


346

ฉันต้องการเพิ่มบางแถวในฐานข้อมูลโดยใช้ Linq ไปยัง SQL แต่ฉันต้องการสร้าง "การตรวจสอบที่กำหนดเอง" ก่อนที่จะเพิ่มแถวเพื่อทราบว่าฉันต้องเพิ่มเปลี่ยนหรือเพิกเฉยแถวที่ไม่เหมาะสม ฉันต้องการเก็บ trafic ระหว่างไคลเอนต์และเซิร์ฟเวอร์ DB ให้น้อยที่สุดเท่าที่จะทำได้และลดจำนวนการค้นหา

เมื่อต้องการทำเช่นนี้ฉันต้องการดึงข้อมูลให้น้อยที่สุดเท่าที่จำเป็นสำหรับการตรวจสอบความถูกต้องและเพียงครั้งเดียวที่จุดเริ่มต้นของกระบวนการ

ฉันคิดว่าจะทำอะไรแบบนี้ แต่เห็นได้ชัดว่ามันไม่ทำงาน ใครมีความคิด?

Dictionary<int, DateTime> existingItems = 
    (from ObjType ot in TableObj
        select (new KeyValuePair<int, DateTime>(ot.Key, ot.TimeStamp))
    )

สิ่งที่ฉันต้องการในตอนท้ายจะเป็นพจนานุกรมโดยไม่ต้องดาวน์โหลดวัตถุ ObjectType ทั้งหมดจาก TableObject

ฉันยังพิจารณารหัสต่อไปนี้ แต่ฉันพยายามหาวิธีที่เหมาะสม:

List<int> keys = (from ObjType ot in TableObj orderby ot.Key select ot.Key).ToList<int>();
List<DateTime> values = (from ObjType ot in TableObj orderby ot.Key select ot.Value).ToList<int>();
Dictionary<int, DateTime> existingItems = new Dictionary<int, DateTime>(keys.Count);
for (int i = 0; i < keys.Count; i++)
{
    existingItems.Add(keys[i], values[i]);
}

คำตอบ:


633

ลองใช้วิธีเช่นดังนั้น:ToDictionary

var dict = TableObj.ToDictionary( t => t.Key, t => t.TimeStamp );

2
@pawan มันเป็นตัวยึดสำหรับแต่ละองค์ประกอบในการแจงนับและใช้กับชนิดของวัตถุในการแจงนับ
tvanfosson

1
@pawan - ดูไม่ถูกต้อง ฉันคาดหวังvar servers = list.Select( s => new { s.ProjectName, Url = "tcp://" + s.BuildMachineName + ":" + s.PortNumber + "/CruiseManager.rem" } ).ToDictionary( s => s.ProjectName, s.Url ); สิ่งนี้จะสร้างพจนานุกรมที่คีย์ด้วยชื่อโปรเจ็กต์ของคู่ชื่อ / url ของโปรเจ็กต์
tvanfosson

3
ทำไมการ.Select( t => new { t.Key, t.TimeStamp } )แสดงออกจึงจำเป็น?
Ben Collins

9
@BenCollins: ฉันคิดว่าตัวกลาง.Selectทำให้ SQL ที่สร้างขึ้นเพื่อเลือก Key และ TimeStamp เท่านั้นแทนที่จะเลือกทุกคอลัมน์
Joey Adams

1
คุณสามารถละเว้นคนกลางนี้ได้Selectหากคุณกำลังทำ Linq to Object (แทนที่จะเป็น Linq ไปยัง SQL)
23919

119

ดูตัวอย่างของคุณฉันคิดว่านี่คือสิ่งที่คุณต้องการ:

var dict = TableObj.ToDictionary(t => t.Key, t=> t.TimeStamp);

ว้าว ... มันอาจจะง่ายอย่างนั้น ... เนื่องจากฉันค่อนข้างใหม่ในการเขียนโปรแกรมฉันจะลองทำและทำโปรไฟล์เล็กน้อยเพื่อให้แน่ใจว่าภายใต้ประทุนฉันไม่ได้รับความนิยมจากวัตถุทั้งหมด ฉันจะให้คุณโพสต์
Tipx

1
ฉันเพิ่งตรวจสอบ น่าเศร้าที่ในขณะที่รับ TableObj มันจะดึงเอาวัตถุทั้งหมดจากฐานข้อมูลดังนั้นฉันเลยได้รับการโจมตีแบบทราฟฟิค ฉันยังตรวจสอบข้อความค้นหาด้วยวิธีที่สองที่ฉันโพสต์ (และต้องการหลีกเลี่ยง) และพวกเขาจะได้รับรายการที่จำเป็นเท่านั้น แน่นอนว่ามันมีการสืบค้น 2 ครั้งดังนั้นเซิร์ฟเวอร์เองจึงต้องค้นหาตารางสองเท่า แต่การทำแผนที่วัตถุนั้นง่ายพอ
Tipx

7
คุณสามารถทำได้: TableObj.Select (t => new {t.Key, t.TimeStamp}) ToDictionary (t => t.Key, t => t.TimeStamp); LinqToSql ควรสังเกตว่าคุณต้องการเพียงสองสิ่ง (จากตัวเลือก) และส่งคืน ฉันไม่แน่ใจว่ามันฉลาดพอที่จะเจาะลึกข้อมูลเฉพาะของ ToDictionary ()
Talljoe

1
NICE! นี่คือผลการสืบค้น: SELECT [t0]. [Key], [t0]. [TimeStamp] จาก [TableObj] AS [t0] ฉันไม่ต้องการรับเครดิตสำหรับสิ่งนี้ดังนั้นไปข้างหน้าและโพสต์ว่าเป็นผู้ประกาศข่าว! :-P
Tipx

8

ลองทำสิ่งต่อไปนี้

Dictionary<int, DateTime> existingItems = 
    (from ObjType ot in TableObj).ToDictionary(x => x.Key);

หรือรุ่นที่ด้อยกว่ารุ่นเต็ม

var existingItems = TableObj.ToDictionary(x => x.Key);

ขอบคุณสำหรับ anwser JaredPar ฉันสอนเกี่ยวกับสิ่งนี้ แต่ฉันคิดว่าสิ่งนี้จะคืนค่าวัตถุทั้งหมดของประเภท ObjType และฉันต้องการหลีกเลี่ยงการดาวน์โหลดวัตถุทั้งหมด
Tipx

@Tipx คุณสามารถให้ข้อมูลบางอย่างเกี่ยวกับสิ่งที่คุณต้องการกรองได้หรือไม่? เพิ่มข้อกรองเป็นไปได้ แต่ผมไม่สามารถบอกได้จากคำถามของคุณสิ่งที่สำคัญ
JaredPar

ทั้งหมดที่ฉันต้องรู้ถ้าจำเป็นต้องเพิ่ม "แถวใหม่" ถูกเพิกเฉยหรือแทนที่แถวอื่นเป็นเวลาประทับของวัตถุ วัตถุในฐานข้อมูลมีฟิลด์มากมายที่ฉันไม่ต้องการสำหรับการตรวจสอบความถูกต้องและฉันไม่ต้องการรับประสิทธิภาพการทำงานในการรับวัตถุทั้งหมด เพื่อให้ง่ายฉันได้ตารางใน BD ที่มี 20 คอลัมน์, 100,000 แถวและฉันต้องการแยกพจนานุกรมโดยใช้ค่าของ 2 คอลัมน์แรก
Tipx

ฉันเพิ่งตรวจสอบการสอบถามเซิร์ฟเวอร์ที่สร้างโดยรหัสนั้นและอย่างที่คุณอาจจะรู้ว่ามันได้รับวัตถุทั้งหมด
Tipx

0

ใช้เนมสเปซ

using System.Collections.Specialized;

ทำอินสแตนซ์ของDataContextClass

LinqToSqlDataContext dc = new LinqToSqlDataContext();

ใช้

OrderedDictionary dict = dc.TableName.ToDictionary(d => d.key, d => d.value);

เพื่อดึงค่าใช้เนมสเปซ

   using System.Collections;

ICollection keyCollections = dict.Keys;
ICOllection valueCollections = dict.Values;

String[] myKeys = new String[dict.Count];
String[] myValues = new String[dict.Count];

keyCollections.CopyTo(myKeys,0);
valueCollections.CopyTo(myValues,0);

for(int i=0; i<dict.Count; i++)
{
Console.WriteLine("Key: " + myKeys[i] + "Value: " + myValues[i]);
}
Console.ReadKey();

สำหรับปุ่มหลายปุ่ม ?
Kiquenet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.