Entity Framework 4 Single () เทียบกับ First () เทียบกับ FirstOrDefault ()


119

ฉันมีปีศาจในการค้นหาการเปรียบเทียบวิธีต่างๆในการค้นหารายการเดียวและเวลาที่ควรใช้แต่ละรายการ

ใครมีลิงค์ที่เปรียบเทียบสิ่งเหล่านี้ทั้งหมดหรือคำอธิบายสั้น ๆ ว่าทำไมคุณถึงใช้อันอื่น? ยังมีตัวดำเนินการอีกหรือไม่ที่ฉันไม่รู้จัก?

ขอบคุณ.

คำตอบ:


205

นี่คือภาพรวมของวิธีการต่างๆ:

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

  • Single () - เมื่อคุณคาดว่าหนึ่งรายการจะถูกส่งกลับโดยแบบสอบถาม สิ่งนี้จะทำให้เกิดข้อยกเว้นหากแบบสอบถามไม่ส่งกลับรายการเดียว

  • SingleOrDefault () - เมื่อคุณคาดว่าจะส่งคืนค่าศูนย์หรือหนึ่งรายการโดยคิวรี (กล่าวคือคุณไม่แน่ใจว่ามีรายการที่มีคีย์ที่กำหนดอยู่หรือไม่) สิ่งนี้จะทำให้เกิดข้อยกเว้นหากแบบสอบถามไม่ส่งคืนศูนย์หรือหนึ่งรายการ

  • ขั้นแรก () - เมื่อคุณคาดหวังว่ารายการหนึ่งหรือหลายรายการจะถูกส่งคืนโดยแบบสอบถาม แต่คุณต้องการเข้าถึงรายการแรกในรหัสของคุณเท่านั้น (การสั่งซื้ออาจมีความสำคัญในการสืบค้นที่นี่) สิ่งนี้จะทำให้เกิดข้อยกเว้นหากแบบสอบถามไม่ส่งคืนอย่างน้อยหนึ่งรายการ

  • FirstOrDefault () - เมื่อคุณคาดว่าจะมีการส่งคืนรายการที่เป็นศูนย์หรือมากกว่าโดยแบบสอบถาม แต่คุณต้องการเข้าถึงรายการแรกในรหัสของคุณเท่านั้น (เช่นคุณไม่แน่ใจว่ามีรายการที่มีคีย์ที่กำหนดอยู่หรือไม่)


1
ขึ้นอยู่กับสถานการณ์ หากคุณรู้ว่าคุณควรจะได้รับระเบียนเดียวกลับจากฐานข้อมูลไม่มากไม่น้อยไปกว่านั้นสำหรับแบบสอบถามที่ระบุ Single () คือสิ่งที่ 'ถูกต้อง' ที่จะใช้ ในสถานการณ์อื่น ๆ คนอื่นอาจเหมาะสมกว่า ใน EF เวอร์ชันก่อนหน้าเรา จำกัด ไว้ที่ First () และ FirstOrDefault () ซึ่งใช้ได้กับสถานการณ์ที่คุณคาดหวังว่าจะมีระเบียนเดียว แต่จะไม่เตือนคุณหากคุณได้รับมากกว่าระเบียนเดียวจริง ๆ ซึ่งอาจมีความสำคัญขึ้นอยู่กับ สถานการณ์.
Steve Willcock

1
ขอบคุณ ฉันไม่เห็นว่าตัวเองต้องการ First () อีกต่อไปโดยที่ Single () จะไม่ดีไปกว่านี้ ถ้าฉันมีความหนาแน่นน้อยกว่าฉันแน่ใจว่าฉันสามารถเข้าใจ / เข้าใจได้ว่าควรใช้ First () เมื่อใด
asfsadf

1
อันดับแรก () เหมาะสมที่สุดในกรณีที่คุณต้องการดึงเฉพาะวัตถุที่มีค่าสูงสุดหรือต่ำสุดของสิ่งที่คุณกำลังสั่งซื้อ ตัวอย่างเช่นค้นหาการขายที่มีมูลค่ารวมสูงสุด Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain

5
ความคิดเห็นทั้งหมดดูแตกต่างที่สำคัญ Find () เป็นวิธีเดียวที่ค้นหาบริบทก่อนที่จะกดปุ่ม db
Yaron Levi

5
อีกประเด็นหนึ่งคือเมื่อค้นหาฐานข้อมูล sql SingleหรือSingleOrDefaultจะค้นหา 2 ระเบียน (ขีด จำกัด 2) ในขณะที่FirstหรือFirstOrDefaultจะค้นหา 1 (ขีด จำกัด 1)
Bart Calixto

22

FirstOrDefaultฉันมักจะมีแนวโน้มที่จะใช้งาน หากคุณต้องการจู้จี้จุกจิกกับการแสดงจริง ๆ คุณควรใช้FirstOrDefaultใน EF ภายใต้ฝาครอบSingleOrDefaultใช้ด้านบน (2) ในแบบสอบถามเนื่องจากจำเป็นต้องตรวจสอบว่ามีแถวที่สองที่ตรงกับเกณฑ์หรือไม่และหากมีจะแสดงข้อยกเว้น โดยพื้นฐานแล้วSingleOrDefaultคุณกำลังบอกว่าคุณต้องการยกเว้นถ้าแบบสอบถามของคุณส่งคืนมากกว่า 1 ระเบียน


5
คุณเคยวัดความแตกต่างของประสิทธิภาพระหว่างFirstOrDefaultและSingleOrDefaultมีนัยสำคัญหรือไม่? ฉันจะบอกว่าเป็นการเพิ่มประสิทธิภาพก่อนกำหนดในกรณีส่วนใหญ่
Steven

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

15

มันง่ายมาก: Singleส่งคืนรายการเดียวและโยนข้อยกเว้นหากไม่มีหรือมากกว่าหนึ่งรายการ Firstจะส่งคืนรายการแรกหรือโยนเมื่อไม่มีรายการ FirstOrDefaultจะส่งคืนรายการแรกหรือส่งคืนค่าเริ่มต้น (ซึ่งnullในกรณีที่ประเภทที่กำหนดเป็นประเภทอ้างอิง) เมื่อไม่มีรายการ

นี่คือลักษณะการทำงานที่ API ควรจะมี อย่างไรก็ตามโปรดทราบว่าการนำไปใช้งานอาจมีลักษณะการทำงานที่แตกต่างออกไป ในขณะที่ Entity Framework ปฏิบัติตามสิ่งนี้ O / RM อย่าง LLBLGen ก็สามารถกลับมาได้เช่นกันnullเมื่อโทรFirstซึ่งเป็นสิ่งที่แปลกมาก นี่เป็นการตัดสินใจที่แปลกมาก (และดื้อรั้น) โดย IMO ของผู้ออกแบบ


ขอบคุณสตีเวน ฉันเดาว่าฉันยังคงสงสัยว่าทำไมคุณถึงใช้อันอื่น? ฉันใช้ FirstOrDefault () มาโดยตลอดและอยากรู้ว่าทำไมตัวอย่างใหม่ ๆ จำนวนมากที่ฉันเคยเห็นจึงเปลี่ยนเป็น Single () มีเหตุผลที่จะเปลี่ยนไปใช้ Single () หรือไม่? มีคนอื่นที่ทำสิ่งเดียวกันนี้ให้ฉันพิจารณาแทนหรือไม่?
asfsadf

7
หากคุณต้องการให้รหัสของคุณ "ล้มเหลวอย่างรวดเร็ว" First () และ Single () ให้รหัสของคุณระบุสิ่งที่คาดหวังได้แม่นยำยิ่งขึ้น (ดังนั้นจึงอาจล้มเหลวเป็นอย่างอื่นได้)
Frank Schwieterman

3
ฉันเห็นด้วยอย่างยิ่งกับ Frank มันเกี่ยวกับการสื่อสารเจตนาด้วย Singleแสดงออกอย่างชัดเจนว่าคุณคาดหวังว่าผลลัพธ์จะมีองค์ประกอบเดียวเท่านั้น
Steven

8

ทั้งสี่วิธีแต่ละวิธีมีที่มาที่ไป แม้ว่าคุณจะมีเพียงสองการดำเนินการที่แตกต่างกัน

  • อันดับแรก - คาดหวังชุดผลลัพธ์ที่มีหลายรายการให้ฉันเป็นรายการแรกในชุดนั้น
  • เดี่ยว - คาดหวังผลลัพธ์เดียวกลับมาให้ฉันรายการนั้น

เวอร์ชัน xxxxOrDefault () เพิ่งเพิ่มใน "ฉันไม่ต้องการให้ผลลัพธ์ที่ว่างเปล่าถูกตั้งค่าเป็นสถานการณ์พิเศษ"


โอเคสำหรับฉันแล้วดูเหมือนว่า First () จะไม่ค่อยมีประโยชน์ ฉันมีช่วงเวลาที่ยากลำบากกับสถานการณ์ที่ Single () ไม่ใช่ตัวเลือกแรก คุณมีมือเดียวอย่างรวดเร็วโดยบังเอิญ? ขอบคุณ
asfsadf

3
น่าเสียดายที่นักพัฒนาจำนวนมากใช้ First () หรือ FirstOrDefault () เป็นมาตรการป้องกันโดยคิดว่าจะหลีกเลี่ยงข้อยกเว้นเมื่อมีศักยภาพในการซ่อนปัญหาที่แท้จริง
Matt H

3

ในอีกด้านหนึ่งคุณสามารถแบ่งวิธีการเหล่านี้ด้วยตรรกะหลักเช่นนี้:

  • เมธอดจะค้นหาฐานข้อมูลโดยตรง : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • เมธอดจะทำการค้นหาในแคชก่อนที่จะออกแบบสอบถามกับฐานข้อมูล : Find ()

สำหรับรายละเอียดประสิทธิภาพบางอย่างโดยเฉพาะในกรณีที่สองคุณสามารถดูได้ที่นี่: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

นอกจากนี้ในกลุ่มแรกคุณสามารถกำหนดคิวรีที่ซับซ้อนได้ แต่ด้วยวิธีการค้นหา ()คุณสามารถระบุคีย์เอนทิตีสำหรับการค้นหาเท่านั้น


0

โดยปกติ Single ()และSingleOrDefault ()จะใช้กับตัวระบุที่ไม่ซ้ำกันเช่น ID ในขณะที่First ()หรือFirstOrDefault ()มักใช้สำหรับข้อความค้นหาที่อาจมีหลายผลลัพธ์ แต่คุณต้องการเฉพาะ"อันดับ 1"1"

Single ()หรือFirst ()จะทำให้เกิดข้อยกเว้นหากไม่มีการส่งคืนผลลัพธ์SingleOrDefault ()และFirstOrDefault () ตรวจจับข้อยกเว้นและส่งคืนค่า null หรือค่าเริ่มต้น (ResultDataType)

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