Entity Framework พร้อมระบบขนาดใหญ่ - จะแบ่งรุ่นอย่างไร


50

ฉันทำงานกับฐานข้อมูล SQL Server ที่มีมากกว่า 1,000 ตารางและอีกไม่กี่ร้อยครั้งและขั้นตอนที่เก็บไว้หลายพันรายการ เรากำลังมองหาที่จะเริ่มใช้ Entity Framework สำหรับโครงการใหม่ของเราและเรากำลังทำงานกับกลยุทธ์ของเราในการทำเช่นนั้น สิ่งที่ฉันวางสายคือวิธีที่ดีที่สุดในการแบ่งตารางออกเป็นรุ่นที่แตกต่างกัน (EDMX หรือ DbContext ถ้าเราใช้รหัสก่อน) ฉันสามารถนึกถึงกลยุทธ์บางอย่างได้ทันทีจากค้างคาว:

  • แยกตามสคีมา
    เรามีตารางของเราแบ่งออกเป็นสกีมาโหล เราสามารถทำหนึ่งแบบต่อสคีมา แม้ว่ามันจะไม่สมบูรณ์แบบก็ตามเนื่องจาก dbo ยังคงมีขนาดใหญ่มากพร้อมกับ 500+ ตาราง / มุมมอง ปัญหาอีกประการหนึ่งคือหน่วยงานบางอย่างจะจบลงด้วยการทำธุรกรรมที่ครอบคลุมหลายรุ่นซึ่งเพิ่มความซับซ้อนแม้ว่าฉันจะถือว่า EF ทำให้ตรงไปตรงมา
  • แยกตามเจตนา
    แทนที่จะกังวลเกี่ยวกับสกีมาแบ่งโมเดลตามเจตนา ดังนั้นเราจะมีรูปแบบที่แตกต่างกันสำหรับแต่ละแอปพลิเคชันหรือโครงการหรือโมดูลหรือหน้าจอขึ้นอยู่กับวิธีที่เราต้องการได้รับเม็ด ปัญหาที่ฉันเห็นด้วยคือมีบางตารางที่จำเป็นต้องใช้ในทุกกรณีเช่น User หรือ AuditHistory อย่างหลีกเลี่ยงไม่ได้ เราเพิ่มสิ่งเหล่านั้นในทุกรุ่น (ละเมิด DRY ที่ฉันคิด) หรือเป็นรูปแบบแยกต่างหากที่ใช้โดยทุกโครงการหรือไม่
  • อย่าแยกเลย - โมเดลยักษ์ตัว
    นี้เห็นได้ชัดว่าง่ายจากมุมมองการพัฒนา แต่จากการวิจัยของฉันและสัญชาตญาณของฉันดูเหมือนว่ามันจะทำงานได้อย่างยอดเยี่ยมทั้งในเวลาออกแบบระยะเวลาการคอมไพล์และเวลาทำงาน

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

นอกจากนี้ยังเป็นปัญหาใน ORM อื่น ๆ เช่น NHibernate? ถ้าเป็นเช่นนั้นพวกเขาคิดวิธีแก้ปัญหาที่ดีกว่า EF หรือเปล่า?


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

@ ขอบคุณ Jaart ฉันเคยใช้ MS DTC มาก่อนและในขณะที่มันค่อนข้างง่ายมันเพิ่มความซับซ้อนเกินกว่า DB txn อย่างง่ายดังนั้นฉันจึงต้องการหลีกเลี่ยงเมื่อใดก็ตามที่เป็นไปได้
RationalGeek

2
4 ปีต่อมาคุณตัดสินใจอะไรและคุณจะแนะนำอะไรตอนนี้
โรรี่

คำตอบ:


31

โดยส่วนตัวแล้วฉันได้ลองทำสคีมาขนาดใหญ่หนึ่งรายการสำหรับเอนทิตีทั้งหมดของฉันในโครงการที่ค่อนข้างซับซ้อน แต่มีขนาดเล็ก (ประมาณ 300 ตาราง) เรามีฐานข้อมูลที่ถูกทำให้เป็นมาตรฐานอย่างมาก (การทำให้เป็นมาตรฐานแบบที่ 5 (ฉันบอกว่าแบบหลวม ๆ )) ที่มีความสัมพันธ์ "หลายต่อหลาย" และการบังคับใช้ความสมบูรณ์แบบอ้างอิงมาก

นอกจากนี้เรายังใช้กลยุทธ์ "อินสแตนซ์เดียวต่อคำขอ" ซึ่งฉันไม่มั่นใจด้วยเช่นกัน

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

ดังนั้นจากประสบการณ์ของฉันฉันขอแนะนำให้สร้าง. edmx ต่อเจตนาแยกต่างหาก สร้างสิ่งที่คุณจะใช้ตามขอบเขตของความต้องการนั้นเท่านั้น คุณอาจมีไฟล์. edmx ที่กำหนดขอบเขตเล็กกว่าสำหรับงานที่มีวัตถุประสงค์และจากนั้นไฟล์ขนาดใหญ่ที่คุณต้องสำรวจความสัมพันธ์ที่ซับซ้อนเพื่อสร้างวัตถุ ฉันไม่แน่ใจว่าจุดมหัศจรรย์นั้นอยู่ที่ไหน แต่ฉันแน่ใจว่ามีจุดหนึ่ง ... lol ...

แม้ว่าโดยแท้แล้วนอกเหนือจากหลุมพรางที่เราเห็นมาแล้ว (การสำรวจที่ซับซ้อน) แล้ว. edmx ขนาดใหญ่ก็ทำงานได้ดีจากมุมมอง "การทำงาน" แต่คุณจะต้องระวังเวทมนตร์ "fixup" ที่บริบททำอยู่เบื้องหลังหากคุณไม่ได้ปิดใช้งานอย่างชัดเจน เช่นเดียวกับการรักษา. edmx ให้สอดคล้องกันเมื่อมีการเปลี่ยนแปลงฐานข้อมูล .. บางครั้งมันง่ายกว่าในการเช็ดพื้นผิวทั้งหมดและสร้างเอนทิตีใหม่ซึ่งใช้เวลาประมาณ 3 นาทีจึงไม่ใช่เรื่องใหญ่

นี่คือทั้งหมดที่มี EntityFramework 4.1 ฉันสนใจที่จะได้ยินเกี่ยวกับทางเลือกและประสบการณ์ของคุณเช่นกัน

และเกี่ยวกับคำถามของคุณใน nHibernate นั่นเป็นคำถามหนอนในความคิดของฉันคุณจะเห่าทั้งสองด้านของรั้ว ... ฉันได้ยินผู้คนมากมายทุบตี EF เพื่อทุบตีโดยไม่ต้องผ่าน ความท้าทายและความเข้าใจถึงความแตกต่างที่ไม่เหมือนใครของ EF เองและถึงแม้ว่าฉันจะไม่เคยใช้ nHibernate ในการผลิตโดยทั่วไปถ้าคุณต้องสร้างสิ่งต่าง ๆ เช่นการแมปด้วยตนเองและชัดเจนคุณจะได้รับการควบคุมที่ จำกัด มากขึ้น สามารถลาก n 'ปล่อยสร้างและเริ่ม CRUD'ing และสอบถามโดยใช้ LINQ ฉันสามารถให้อึเกี่ยวกับเมล็ด

ฉันหวังว่านี่จะช่วยได้.


1
FYI - มียูทิลิตี้การทำแผนที่ NHibernate ที่ทำให้การแมปเหล่านี้ง่ายและเป็นอัตโนมัติมาก
Ganders

@ganders - มี UI และการรวม IDE อย่างไร ฉันสมมติว่าคุณชี้ไปที่แหล่งข้อมูลและเคารพความสมบูรณ์ของการอ้างอิงและการสำรวจวัตถุและสร้างการแมปวัตถุ?
hanzolo

1
ใช่ (GUI) ฉันไม่มีปัญหากับมันจนถึงตอนนี้ ใช้กับโครงการหรือเว็บไซต์ต่าง ๆ 4 หรือ 5 โครงการ หมายเหตุ: ฉันใช้กับ Fluent NHibernate ซึ่งทำแผนที่ใน c # code ไม่ใช่ในไฟล์ config / xml นี่คือลิงค์: nmg.codeplex.com
ganders

13

ให้ฉันเริ่มต้นด้วยการชี้แจงอย่างง่าย ๆ : ฉันไม่มีประสบการณ์กับฐานข้อมูลขนาดใหญ่เช่นนี้ดังนั้นคำตอบที่เหลือของฉันไม่ได้ขึ้นอยู่กับตัวอย่างในโลกแห่งความเป็นจริง

ดังนั้นคุณมีฐานข้อมูลขนาดใหญ่และคุณต้องการใช้กับ ORM / EF ฉันจะไปกับตัวเลือกที่สอง นี่คือคำอธิบายง่ายๆของฉันทำไม:

  • การทำแผนที่เพิ่มความซับซ้อน ไม่จำเป็นต้องเพิ่มความซับซ้อนกับเอนทิตีแอปพลิเคชันปัจจุบันของคุณ / โครงการ / โมดูลที่ไม่ต้องการ แต่ไม่ทำให้ระดับความละเอียดต่ำเกินไป การมีชุดการแมปแยกกันต่อหน้าจอจะไม่ช่วยคุณเช่นกัน
  • คุณต้องการที่จะบรรลุหน่วยงาน คุณควรจะสามารถระบุสิ่งที่โมดูลตารางต้องการในกรณีส่วนใหญ่ (ไม่จำเป็นในทุกกรณี) หากคุณวางตารางเหล่านี้ไว้ในชุดการแมปเดียวคุณจะสามารถจัดการการอ่านและการแก้ไขข้อมูลโดยอินสแตนซ์บริบทเดียวนั่นคือสิ่งที่ควรเป็นเป้าหมายสูงสุดของคุณ
  • ฉันไม่แน่ใจว่าคุณหมายถึงอะไรตามรุ่น แต่ถึงแม้จะมีชุดการแมปที่แตกต่างกันคุณสามารถแชร์คลาสระหว่างชุดการแมปโดยใช้ประเภทเอนทิตีเดียวกัน ดังนั้นหากคุณใช้ตารางผู้ใช้ในสองโมดูลคุณไม่จำเป็นต้องมีสองคลาสผู้ใช้เพื่อเป็นตัวแทนของเดียวกัน คุณยังคงสามารถใช้ตารางเดี่ยวและในกรณีของการทำแผนที่รหัส (aka รหัสแรก) คุณยังสามารถกำหนดการทำแผนที่ครั้งเดียวและโหลดไปยังชุดการแมปหลายชุดเพื่อให้หลักการ DRY ไม่ได้ละเมิด แต่วิธีการที่รหัสแรกมีข้อ จำกัด มากขึ้น เพื่อดูและขั้นตอนการจัดเก็บ EDMX ทำให้สิ่งนี้ยากขึ้น คุณยังสามารถใช้คลาสซ้ำได้ แต่ไม่สามารถใช้การทำแผนที่ซ้ำได้
  • สิ่งที่เกี่ยวกับการค้นหาข้ามโมดูล? คำถามเหล่านี้อาจเกิดขึ้นได้ แต่โดยความจริงแล้วไม่ใช่ว่าทุกอย่างจะต้องได้รับการจัดการโดย EF คุณสามารถใช้ประโยชน์จาก EF สำหรับกรณีทั่วไปเพื่อลดความซับซ้อนในการเข้าถึงข้อมูลปกติ แต่ถ้าคุณมีความต้องการในการสืบค้นพิเศษซึ่งรวมตารางของ 5 โมดูลที่แตกต่างกันคุณสามารถเรียกใช้งานได้โดยตรง การแทนที่การเข้าถึงข้อมูลดั้งเดิม 100% อาจเป็นเรื่องยากซับซ้อนและต้านการผลิต
  • ประเด็นสุดท้ายก็คือใช้งานได้จริง: ฉันไม่เชื่อว่า VS tooling พร้อมที่จะทำงานกับชุดใหญ่ของวัตถุ - ไม่ใช่นักออกแบบไม่ใช่แม้แต่เครื่องมือการนำเข้า ฉันเคยทำงานกับฐานข้อมูลขนาดใหญ่มากด้วยการเข้าถึงข้อมูลแบบดั้งเดิมและโครงการฐานข้อมูล SQL ใน VS2008 - ประสบการณ์ของผู้ใช้กับโครงการที่ซับซ้อนนั้นแย่มาก คุณต้องรักษาจำนวนของตารางที่ใช้ต่ำ - หมวกสำหรับนักออกแบบควรอยู่ระหว่าง 100-200 แต่แม้ 100 ตารางที่จัดการโดยบริบทเดียว (ชุดการแมป) ฟังดูเหมือนรับผิดชอบมากเกินไปสำหรับหนึ่งคลาส (สมมติว่าคุณจะมี 100 ชุดคุณสมบัติ สัมผัสกับบริบท - มันไม่ได้ดูเหมือนการออกแบบที่ดี)

4

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

"สถาปนิกที่ดีจะเพิ่มจำนวนการตัดสินใจที่ไม่ได้ทำ" โรเบิร์ตซี. มาร์ติน

http://cleancoder.posterous.com/architecture-deference


3

ฉันใช้วิธีการแบบไฮบริด - สิ่งที่ OLTP ได้รับการจัดการโดย EF ในขณะที่การทำงานหนักเช่นการแทรกแบตช์การอัปเดตจำนวนมากแบบสอบถามรายงาน ฯลฯ จะถูกจัดการโดย Procs ที่เก็บไว้ นอกจากนี้ยังทำให้เส้นทางการย้ายข้อมูลง่ายขึ้นหากคุณไม่ได้เขียนชั้นข้อมูลใหม่ทั้งหมดในครั้งเดียว


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

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

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

ฉันจะบอกว่าต้นไม้วัตถุขนาดใหญ่และโครงสร้างข้อมูลที่เป็นมาตรฐานไปจับมือเมื่อจัดการกับ schema ขนาดใหญ่ของ
hanzolo

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