SqlDataAdapter กับ SqlDataReader


131

อะไรคือความแตกต่างระหว่างการใช้ SqlDataAdapter กับ SqlDataReader ในการรับข้อมูลจาก DB

ฉันกำลังมองหาข้อดีข้อเสียของพวกเขาโดยเฉพาะรวมถึงความเร็วและประสิทธิภาพของหน่วยความจำ

ขอบคุณ

คำตอบ:


194

SqlDataReader:

  • เปิดการเชื่อมต่อค้างไว้จนกว่าคุณจะเสร็จสิ้น (อย่าลืมปิด!)
  • โดยทั่วไปสามารถทำซ้ำได้เพียงครั้งเดียว
  • ไม่เป็นประโยชน์สำหรับการอัปเดตกลับไปที่ฐานข้อมูล

ในทางกลับกันมัน:

  • มีบันทึกในหน่วยความจำครั้งละหนึ่งรายการเท่านั้นแทนที่จะเป็นชุดผลลัพธ์ทั้งหมด (อาจมีขนาดใหญ่มาก )
  • เร็วที่สุดเท่าที่จะทำได้สำหรับการทำซ้ำครั้งนั้น
  • ช่วยให้คุณเริ่มประมวลผลผลลัพธ์ได้เร็วขึ้น (เมื่อบันทึกแรกพร้อมใช้งาน) สำหรับแบบสอบถามบางประเภทสิ่งนี้อาจเป็นเรื่องใหญ่มาก

SqlDataAdapter / ชุดข้อมูล

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

ในราคา:

  • ใช้หน่วยความจำที่สูงขึ้นมาก
  • คุณรอจนกว่าข้อมูลทั้งหมดจะโหลดก่อนที่จะใช้ข้อมูลใด ๆ

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

สำหรับข้อมูลเพิ่มเติมโปรดดูที่เอกสารไมโครซอฟท์อย่างเป็นทางการ


5
DataSet เป็นที่เก็บข้อมูลในหน่วยความจำในขณะที่ datareader เป็นเพียงสื่อกลางในการดึงข้อมูล ในหมายเหตุที่สั้นกว่าคุณสามารถเรียกใช้การสืบค้น Linq บน DataSet แต่ไม่สามารถเรียกใช้บนดาต้าเรเดอร์ได้
Partha Choudhury

อันที่จริงด้วยโค้ดพิเศษเล็กน้อยคุณสามารถเรียกใช้การสืบค้น linq (หรืออย่างน้อยหนึ่งแบบสอบถาม) บนดาต้าเรเดอร์ได้ เพียงใช้บล็อกตัววนซ้ำเพื่อให้ DataReader ส่งคืนเป็น IDataRecord ภายในwhile (reader.Read())ลูปของคุณ
Joel Coehoorn

7
คำตอบนี้ทำให้เข้าใจผิด หากคุณรวมออบเจ็กต์ SqlConnection และ SqlDataReader ของคุณด้วยคำสั่ง "ใช้" (ตามที่คุณควรจะเป็นเพราะมันเป็น IDisposable) การเชื่อมต่อจะถูกปิดโดยอัตโนมัติ และคุณสามารถใช้ DataSet กับ SqlDataReader: เพียงแค่เรียก DataSet.Load (SqlDataReader)
RickNZ

4
@RickNZ อย่าด่วนเชื่อโดยใช้งบเพื่อปิดสิ่งต่างๆให้คุณ พวกเขาเรียกเมธอด Dispose () ของอ็อบเจ็กต์ไม่ใช่เมธอด Close () และฉันได้พบอย่างน้อยหนึ่งกรณีที่ Dispose ไม่ได้ปิดอ็อบเจ็กต์ให้ฉันจริงๆ ที่ดีที่สุดคือรวมการเรียกที่ชัดเจนไปยังวิธีการปิดไว้ในบล็อกที่ใช้
Cdaragorn

5
@Cdaragorn เอกสาร MSDN มักจะค่อนข้างชัดเจนเกี่ยวกับ Close () เทียบกับ Dispose () ในกรณีของ SqlConnection ตัวอย่างเช่นเอกสารบอกว่า Close () และ Dispose () มีฟังก์ชันเทียบเท่ากัน ฉันไม่คัดค้านการเรียก Close () แต่การเรียก Dispose () ควรอยู่ที่นั่นเช่นกันสำหรับ IDisposables ทั้งหมด - และวิธีที่สะอาดที่สุดในการทำเช่นนั้นคือการใช้คำสั่ง ในกรณีที่คุณรู้ว่า Dispose () ไม่ได้เรียก Close () คุณควรเรียก Close () ภายในบล็อกในที่สุดหากทำได้ไม่ใช่ภายในบล็อกการใช้งาน (ดังนั้นจึงยังคงถูกเรียกหากมีข้อยกเว้น)
RickNZ

17

คำตอบนั้นสามารถค่อนข้างกว้าง

โดยพื้นฐานแล้วความแตกต่างที่สำคัญสำหรับฉันที่มักจะมีผลต่อการตัดสินใจของฉันว่าจะใช้กับ SQLDataReader คุณกำลัง "สตรีม" ข้อมูลจากฐานข้อมูล ด้วย SQLDataAdapter คุณกำลังแยกข้อมูลจากฐานข้อมูลลงในวัตถุที่สามารถสืบค้นเพิ่มเติมได้เองรวมทั้งดำเนินการ CRUD

เห็นได้ชัดว่ากระแสข้อมูล SQLDataReader เร็วกว่ามาก แต่คุณสามารถประมวลผลได้ครั้งละหนึ่งระเบียนเท่านั้น ด้วย SQLDataAdapter คุณจะมีคอลเลกชันที่สมบูรณ์ของแถวที่ตรงกันกับแบบสอบถามของคุณจากฐานข้อมูลเพื่อใช้งาน / ส่งผ่านโค้ดของคุณ

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

ขออภัย VB ของฉัน แต่นี่เป็นจำนวนขั้นต่ำของรหัสที่คุณควรมีเมื่อใช้ SqlDataReader:

Using cn As New SqlConnection("..."), _
      cmd As New SqlCommand("...", cn)

    cn.Open()
    Using rdr As SqlDataReader = cmd.ExecuteReader()
        While rdr.Read()
            ''# ...
        End While
    End Using
End Using     

เทียบเท่า C #:

using (var cn = new SqlConnection("..."))
using (var cmd = new SqlCommand("..."))
{
    cn.Open();
    using(var rdr = cmd.ExecuteReader())
    {
        while(rdr.Read())
        {
            //...
        }
    }
}

หากเป้าหมายของคุณคือการรับข้อมูลโดยใช้แบบสอบถามแบบเลือกบนฐานข้อมูลและเข้าถึงเฉพาะข้อมูลนี้ในแถวที่แตกต่างกันไปที่แถว rpevious เป็นต้นจากนั้นคุณสามารถใช้ SQLDatareader และโหลดลงใน datatable โดยใช้ dtable.Load (rdr) จากนั้นเรียกดูขึ้นและลงภายใน datatable นี้ คุณสามารถใช้วิธีนี้แทน DataAdapter ...
ตัวแปร

14

โดยทั่วไปแล้ว SqlDataAdapter จะใช้เพื่อเติม DataSet หรือ DataTable ดังนั้นคุณจะสามารถเข้าถึงข้อมูลได้หลังจากปิดการเชื่อมต่อของคุณแล้ว (การเข้าถึงที่ไม่ได้เชื่อมต่อ)

SqlDataReader เป็นเคอร์เซอร์ที่เชื่อมต่อไปข้างหน้าอย่างเดียวและรวดเร็วซึ่งมักจะเร็วกว่าการกรอก DataSet / DataTable

นอกจากนี้ด้วย SqlDataReader คุณจัดการกับข้อมูลของคุณทีละบันทึกและไม่เก็บข้อมูลใด ๆ ไว้ในหน่วยความจำ เห็นได้ชัดว่าด้วย DataTable หรือ DataSet คุณมีค่าใช้จ่ายในการจัดสรรหน่วยความจำ

หากคุณไม่จำเป็นต้องเก็บข้อมูลของคุณไว้ในหน่วยความจำดังนั้นสำหรับการแสดงผลข้อมูลเท่านั้นให้ไปที่ SqlDataReader หากคุณต้องการจัดการกับข้อมูลของคุณในลักษณะที่ขาดการเชื่อมต่อให้เลือก DataAdapter เพื่อกรอก DataSet หรือ DataTable


10

ใช้ SqlDataAdapter เมื่อต้องการเติม DataSet / DataTable ในหน่วยความจำจากฐานข้อมูล จากนั้นคุณจะมีความยืดหยุ่นในการปิด / กำจัดการเชื่อมต่อส่งผ่านข้อมูล / ตั้งค่าในหน่วยความจำ จากนั้นคุณสามารถจัดการข้อมูลและเก็บกลับเข้าไปในฐานข้อมูลโดยใช้อะแดปเตอร์ข้อมูลร่วมกับ InsertCommand / UpdateCommand

ใช้ SqlDataReader เมื่อต้องการการเข้าถึงข้อมูลที่รวดเร็วและมีหน่วยความจำต่ำโดยไม่จำเป็นต้องมีความยืดหยุ่นเช่นการส่งผ่านข้อมูลตามตรรกะทางธุรกิจของคุณ วิธีนี้เหมาะสมกว่าสำหรับการดึงข้อมูลปริมาณข้อมูลขนาดใหญ่ที่รวดเร็วและใช้หน่วยความจำต่ำเนื่องจากไม่ได้โหลดข้อมูลทั้งหมดลงในหน่วยความจำทั้งหมดในครั้งเดียว - ด้วยวิธี SqlDataAdapter DataSet / DataTable จะเต็มไปด้วยข้อมูลทั้งหมดดังนั้นหาก มีแถวและคอลัมน์จำนวนมากซึ่งจะต้องใช้หน่วยความจำจำนวนมากในการเก็บรักษา


0

ฟังก์ชัน Fill ใช้ DataReader ภายใน หากการพิจารณาของคุณคือ "อันไหนมีประสิทธิภาพมากกว่ากัน" จากนั้นใช้ DataReader ในการวนซ้ำแบบแน่นที่เติมข้อมูลคอลเลกชันทีละเรกคอร์ดมีแนวโน้มที่จะโหลดในระบบเช่นเดียวกับการใช้ DataAdapter.Fill

(System.Data.dll, System.Data.Common.DbDataAdapter, FillInternal.)

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