NHibernate เทียบกับ LINQ เป็น SQL


117

ในฐานะคนที่ไม่ได้ใช้เทคโนโลยีอย่างใดอย่างหนึ่งในโครงการในโลกแห่งความเป็นจริงฉันสงสัยว่ามีใครรู้บ้างว่าทั้งสองนี้เสริมกันอย่างไรและฟังก์ชันการทำงานของพวกเขาทับซ้อนกันมากแค่ไหน?

คำตอบ:


113

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

ปัญหาเกี่ยวกับรูปแบบตารางต่อคลาสคือโครงสร้างฐานข้อมูลของคุณมีอิทธิพลโดยตรงต่อการออกแบบโดเมนของคุณ ตัวอย่างเช่นสมมติว่าคุณมีตารางลูกค้าที่มีคอลัมน์ต่อไปนี้เพื่อเก็บข้อมูลที่อยู่หลักของลูกค้า:

  • ที่อยู่ถนน
  • เมือง
  • สถานะ
  • ซิป

สมมติว่าคุณต้องการเพิ่มคอลัมน์สำหรับที่อยู่ทางไปรษณีย์ของลูกค้าด้วยดังนั้นคุณจึงเพิ่มคอลัมน์ต่อไปนี้ในตารางลูกค้า:

  • MailingStreetAddress
  • MailingCity
  • MailingState
  • MailingZip

เมื่อใช้ LINQ กับ SQL อ็อบเจ็กต์ Customer ในโดเมนของคุณจะมีคุณสมบัติสำหรับแต่ละคอลัมน์ทั้งแปดนี้ แต่ถ้าคุณทำตามรูปแบบการออกแบบที่ขับเคลื่อนด้วยโดเมนคุณอาจได้สร้างคลาสที่อยู่และให้คลาสลูกค้าของคุณมีคุณสมบัติที่อยู่สองคุณสมบัติหนึ่งสำหรับที่อยู่ทางไปรษณีย์และอีกหนึ่งรายการสำหรับที่อยู่ปัจจุบัน

นั่นเป็นตัวอย่างง่ายๆ แต่แสดงให้เห็นว่ารูปแบบตารางต่อคลาสสามารถนำไปสู่โดเมนที่ค่อนข้างเหม็นได้อย่างไร ในที่สุดก็ขึ้นอยู่กับคุณ อีกครั้งสำหรับแอปง่ายๆที่ต้องการฟังก์ชัน CRUD พื้นฐาน (สร้างอ่านอัปเดตลบ) LINQ เป็น SQL นั้นเหมาะอย่างยิ่งเนื่องจากความเรียบง่าย แต่โดยส่วนตัวแล้วฉันชอบใช้ NHibernate เพราะมันช่วยให้โดเมนสะอาดขึ้น

แก้ไข: @lomaxx - ใช่ตัวอย่างที่ฉันใช้นั้นเรียบง่ายและอาจได้รับการปรับให้ทำงานได้ดีกับ LINQ เป็น SQL ฉันต้องการให้มันเป็นพื้นฐานที่สุดเท่าที่จะทำได้เพื่อขับรถกลับบ้าน ประเด็นยังคงอยู่แม้ว่าจะมีหลายสถานการณ์ที่โครงสร้างฐานข้อมูลของคุณกำหนดโครงสร้างโดเมนของคุณอาจเป็นความคิดที่ไม่ดีหรืออย่างน้อยก็นำไปสู่การออกแบบ OO ที่ไม่เหมาะสม


4
คุณสามารถโค้ดการใช้งานที่เก็บของคุณโดยใช้ Linq To SQL ซึ่งมีประโยชน์มาก
Nicolas Dorier

1
ฉันคิดว่ามันไม่ใช่ ActiveRecord แม้แต่คลาสที่แมปจะห่อหุ้มตรรกะโครงสร้างพื้นฐานบางอย่าง รูปแบบ ActiveRecord จะเป็นถ้าคุณมี Customer.Save () L2S ใช้รูปแบบ Unit of Work ด้วยคลาส DataContext เช่น Session ใน nHibernate แต่ NH มีแนวทาง POCO ที่แท้จริง
Hrvoje Hudo

1
@kevin "LINQ เป็น SQL ใช้รูปแบบระเบียนที่ใช้งานอยู่" ไม่ถูกต้อง เหมือนกับการบอกว่า ADO.NET ใช้ active record หรือ NHibernate ใช้ active record เป็นเทคโนโลยีการเข้าถึงข้อมูลทั้งหมดและไม่บังคับใช้รูปแบบการเข้าถึงข้อมูลใด ๆ โดยเฉพาะ โดยส่วนตัวฉันชอบใช้ linq-to-sql กับรูปแบบพื้นที่เก็บข้อมูล คุณถูกต้องที่ linq-to-sql ไม่รองรับการแมปที่ซับซ้อนเช่นเดียวกับ NHibernate
liammclennan

1
สิ่งที่เกี่ยวกับการทำให้ฐานข้อมูลของคุณเป็นปกติแทนและปล่อยให้ DAL ของคุณถูกสร้างโดยเครื่องมือเช่น SQLMetal?
Alex

3
@CoffeeAddict เมื่อความไม่ตรงกันของอิมพีแดนซ์มากเกินไปที่จะทนได้นั่นคือเมื่อแอปพลิเคชันของคุณซับซ้อนเกินไปที่จะใช้ LINQ กับ SQL บน imo สาเหตุที่ตัวอย่างของฉันส่งกลิ่นเป็นเพราะการใช้ LINQ กับ SQL จะส่งผลให้มีคุณสมบัติ 8 อย่างตรงข้ามกับ 2 และจำกัดความสามารถของคุณในการทำสิ่งต่างๆเช่นใช้ฟังก์ชันที่ใช้ในคลาส Address หรือใช้รูทีนในคลาส Address ที่คุณจะทำได้ ถ้าคุณเคยใช้ NHibernate
Kevin Pang

26

สองจุดที่พลาดไป:

  • LINQ เป็น SQL ไม่ทำงานกับ Oracle หรือฐานข้อมูลใด ๆ นอกเหนือจาก SqlServer อย่างไรก็ตามบุคคลที่ 3 จะให้การสนับสนุนที่ดีสำหรับ Oracle เช่นdevart ของ dotConnect , DbLinq , Mindscape ของ LightSpeedและALinq (ฉันไม่มีประสบการณ์ส่วนตัวเกี่ยวกับสิ่งเหล่านี้)

  • Linq ถึง NHibernateช่วยให้คุณใช้ Linq กับ Nhiberate ได้ดังนั้นจึงอาจลบเหตุผลที่จะไม่ใช้ออกไป

นอกจากนี้อินเทอร์เฟซใหม่ที่ใช้งานง่ายของ Nhibernateดูเหมือนว่าจะทำให้การกำหนดค่าการทำแผนที่ของ Nhibernate เจ็บปวดน้อยลง (ลบจุดเจ็บปวดของ Nhibernate ออกหนึ่งจุด)


ปรับปรุง

Linq ถึง Nhiberate ดีกว่าใน Nhiberate v3 ที่ตอนนี้อยู่ในอัลฟ่าอัลฟาดูเหมือนว่า Nhiberate v3 อาจจัดส่งในช่วงปลายปีนี้

Entity กรอบการทำงานเป็นของสุทธิ 4 ยังเริ่มที่จะมีลักษณะเหมือนตัวจริง


2
Linq ถึง NHibernate ยังอยู่ในช่วงเริ่มต้น ไม่ใช่การนำไปใช้งานที่สมบูรณ์และมีเนื้อหาไม่พร้อมสำหรับการใช้งานจริง
liammclennan

LinqConnect 2.0 รุ่นใหม่นำเสนอคุณลักษณะเพิ่มเติมเพื่อความสะดวกเช่นการสนับสนุนการสืบทอดตารางต่อประเภทการสนับสนุน PLINQ และฟังก์ชันการอัปเดตเป็นกลุ่ม ORM Designer (Devart Entity Developer) มีการรองรับ Model First และคุณสมบัติ Mapping Synchronization แล้ว รายละเอียดเพิ่มเติม: devart.com/news/2010/dotconnects600.html
Devart

23

@ เควิน: ฉันคิดว่าปัญหาของตัวอย่างที่คุณนำเสนอคือคุณใช้การออกแบบฐานข้อมูลที่ไม่ดี ฉันคิดว่าคุณจะสร้างตารางลูกค้าและตารางที่อยู่และทำให้ตารางเป็นปกติ หากคุณทำเช่นนั้นคุณสามารถใช้ Linq To SQL สำหรับสถานการณ์ที่คุณกำลังแนะนำได้ Scott Guthrie มีบทความมากมายเกี่ยวกับการใช้ Linq To SQLซึ่งฉันขอแนะนำให้คุณลองดู

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

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

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

ข้อแตกต่างหลักที่นี่คือไวยากรณ์แบบสอบถาม Linq ถูกตรวจสอบในเวลาคอมไพล์โดยคอมไพเลอร์เพื่อให้แน่ใจว่าการสืบค้นของคุณถูกต้อง

สิ่งที่ต้องระวังสำหรับ linq คือมันมีให้ใช้งานใน. net 3.x เท่านั้นและรองรับเฉพาะใน VS2008 เท่านั้น NHibernate มีให้ใน 2.0 และ 3.x เช่นเดียวกับ VS2005

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


15
จะเกิดอะไรขึ้นถ้าคุณกำลังเขียนโค้ดกับโครงสร้างฐานข้อมูลเดิมที่คุณไม่สามารถเปลี่ยนแปลงได้เนื่องจากรองรับแอปอื่น ๆ คุณต้องการให้โมเดลโดเมนของคุณสืบทอดการออกแบบฐานข้อมูลที่ไม่ดีหรือคุณต้องการสร้างแบบจำลองโดเมนที่สมบูรณ์ซึ่งสามารถแตกต่างกันไปโดยไม่ขึ้นกับโครงสร้างฐานข้อมูล
Larry Foulkrod

7

NHibernate ที่คล่องแคล่วสามารถสร้างไฟล์การแมปของคุณตามหลักการง่ายๆ ไม่มีการเขียน XML และพิมพ์ผิด

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

หากคุณกำลังจะใช้เอนทิตีของคุณที่ตัดการเชื่อมต่อจาก DataContext - ในสถานการณ์ WCF เช่นคุณอาจมีปัญหามากมายในการเชื่อมต่อกับ DataContext อีกครั้งเพื่ออัปเดตการเปลี่ยนแปลง ฉันไม่มีปัญหากับ NHibernate

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


2
ในกรณีที่คนอื่นอ่านโพสต์ของคุณและกำลังคิดที่จะกระโดดเรือด้วยเช่นกัน.ObjectTrackingEnabled = falseคุณDataContextจะช่วยแก้ปัญหาการติดตามการเปลี่ยนแปลงของคุณได้ ตราบใดที่คุณซื้อเป็นรูปแบบหน่วยการทำงานและไม่ต้องการทำ DDD Linq-to-SQL ก็มอบให้
mattmc3

" เราจำเป็นต้องเปลี่ยนจาก Linq เป็น SQL เป็น NHibernate ด้วยเหตุผลด้านประสิทธิภาพ " - หลังจากใช้ [Fluent ไม่น้อยไปกว่า] NHibernate มาสองสามปีแล้วฉันรู้สึกดีสำหรับคุณ ฉันคิดว่าเราโกงเป็นส่วนใหญ่และลงเอยด้วยการเขียน SQL แบบเนทีฟสำหรับจุดกดดันด้านประสิทธิภาพจริง จะเป็นเรื่องน่าสนใจที่จะได้ยินการอัปเดต (หกปีต่อมา ... ) เกี่ยวกับการโยกย้ายของคุณเป็นอย่างไรและคุ้มค่าหรือไม่
ruffin

5

คุณช่วยอธิบายความหมายของ "LINQ" ได้หรือไม่?

LINQ ไม่ใช่เทคโนโลยีการเข้าถึงข้อมูล แต่เป็นเพียงคุณลักษณะภาษาที่รองรับการสืบค้นเป็นโครงสร้างดั้งเดิม สามารถค้นหาโมเดลวัตถุใด ๆ ที่รองรับอินเทอร์เฟซเฉพาะ (เช่น IQueryable)

หลายคนอ้างถึง LINQ To SQL ว่า LINQ แต่นั่นไม่ถูกต้องเลย Microsoft เพิ่งเปิดตัว LINQ To Entities ด้วย. NET 3.5 SP1 นอกจากนี้ NHibernate ยังมีอินเทอร์เฟซ LINQ ดังนั้นคุณสามารถใช้ LINQ และ NHibernate เพื่อรับข้อมูลของคุณ


2

โดย LINQ ฉันสมมติว่าคุณหมายถึง LINQ เป็น SQL เนื่องจาก LINQ โดยตัวมันเองไม่มีฐานข้อมูล "goings on" ที่เกี่ยวข้อง เป็นเพียงภาษาแบบสอบถามที่มี syntac sugar เป็นส่วนประกอบเพื่อให้มีลักษณะเป็น SQL-ish

ในตัวอย่างพื้นฐานทั่วไป NHibernate และ LINQ ถึง SQL ดูเหมือนว่าทั้งคู่กำลังแก้ปัญหาเดียวกัน เมื่อคุณผ่านพ้นไปคุณจะรู้ทันทีว่า NHibernate รองรับคุณสมบัติมากมายที่ช่วยให้คุณสร้างโมเดลโดเมนที่สมบูรณ์ได้อย่างแท้จริง นอกจากนี้ยังมีโครงการ LINQ ถึง NHibernate ที่ให้คุณใช้ LINQ เพื่อค้นหา NHibernate ในลักษณะเดียวกับที่คุณใช้ LINQ กับ SQL


1

ก่อนอื่นให้แยกสองสิ่งที่แตกต่างกัน: การสร้างแบบจำลองฐานข้อมูลเกี่ยวข้องกับข้อมูลในขณะที่การสร้างแบบจำลองวัตถุเกี่ยวข้องกับเอนทิตีและความสัมพันธ์

ข้อดีของ Linq-to-SQL คือการสร้างคลาสจากสคีมาฐานข้อมูลอย่างรวดเร็วเพื่อให้สามารถใช้เป็นอ็อบเจ็กต์เรกคอร์ดที่ใช้งานอยู่ (ดูนิยามรูปแบบการออกแบบเรกคอร์ดที่ใช้งานอยู่)

ข้อดีของ NHibernate คือให้ความยืดหยุ่นระหว่างการสร้างแบบจำลองวัตถุและการสร้างแบบจำลองฐานข้อมูล ฐานข้อมูลสามารถสร้างแบบจำลองเพื่อสะท้อนข้อมูลของคุณได้ดีที่สุดโดยคำนึงถึงประสิทธิภาพเช่น แม้ว่าการสร้างแบบจำลองออบเจ็กต์ของคุณจะสะท้อนให้เห็นถึงองค์ประกอบของกฎธุรกิจได้ดีที่สุดโดยใช้แนวทางเช่นการออกแบบโดเมนที่ขับเคลื่อนด้วย (ดูความคิดเห็นของ Kevin Pang)

ด้วยฐานข้อมูลเดิมที่มีการสร้างแบบจำลองและ / หรือรูปแบบการตั้งชื่อที่ไม่ดี Linq-to-SQL จะสะท้อนโครงสร้างและชื่อที่ไม่ต้องการนี้ไปยังคลาสของคุณ อย่างไรก็ตาม NHibernate สามารถซ่อนความยุ่งเหยิงนี้ได้ด้วยตัวทำแผนที่ข้อมูล

ในโครงการกรีนฟิลด์ที่ฐานข้อมูลมีการตั้งชื่อที่ดีและมีความซับซ้อนต่ำ Linq-to-SQL อาจเป็นทางเลือกที่ดี

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

ในทางกลับกันเส้นโค้งการเรียนรู้ของ Linq-to-SQL นั้นเล็กกว่า NHibernate


0

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


0

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

MyDataContext db = new MyDataContext();
List<CUSTOMER_ORDER_LINEITEMResult> records = db.CUSTOMER_ORDER_LINEITEM(pram1, param2 ...).ToList<CUSTOMER_ORDER_LINEITEMResult>();

คุณสามารถใช้คุณบันทึกวัตถุใน foreach loop ได้เช่นกันซึ่ง NHibernate ไม่รองรับ

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