ควรใช้รูปแบบพื้นที่เก็บข้อมูลเมื่อใด


20

ฉันได้อ่านเมื่อเร็ว ๆ นี้ว่าไม่ใช่วิธีปฏิบัติที่ดีในการใช้รูปแบบพื้นที่เก็บข้อมูลร่วมกับ ORM จากความเข้าใจของฉันนี้เป็นเพราะนามธรรมที่พวกเขาให้มากกว่าฐานข้อมูล SQL รั่วไหลเกินกว่าที่จะอยู่ในรูปแบบ

ฉันมีคำถามสองสามข้อเกี่ยวกับเรื่องนี้:

  1. คุณจะทำอย่างไรถ้าคุณต้องการเปลี่ยน ORM คุณจะมีรหัสเฉพาะ ORM ในแอปพลิเคชันของคุณหากคุณไม่มีในที่เก็บ

  2. รูปแบบที่เก็บยังคงใช้ได้เมื่อไม่ได้ใช้ ORM และคุณใช้ ADO.NET สำหรับการเข้าถึงข้อมูลและการเติมข้อมูลวัตถุด้วยตัวเอง?

  3. หากคุณใช้ ORM แต่ไม่ใช่รูปแบบที่เก็บที่คุณเก็บแบบสอบถามที่ใช้บ่อย จะเป็นการดีหรือไม่ที่จะแสดงแต่ละแบบสอบถามเป็นคลาสและมีโรงงานแบบสอบถามบางประเภทเพื่อสร้างอินสแตนซ์


1
1) คุณจะไม่สามารถเปลี่ยน ORM ได้เนื่องจากพฤติกรรมที่แตกต่างกันแม้ว่าทั้งสองรองรับ linq พวกเขาจะทำงานแตกต่างกันพอที่จะทำให้แอปพลิเคชันของคุณแตกหัก เช่นพฤติกรรมการโหลดขี้เกียจ, การติดตามสิ่งสกปรก, พร็อกซี่ผี ฯลฯ อย่างไรก็ตามมันเป็นเรื่องดีที่สามารถสลับ ORM สำหรับการใช้งานแบบ in-mem สำหรับการทดสอบ ..
Roger Johansson

สำหรับสิ่งที่คุ้มค่าการสนทนาของฉันกับ Repository / ORM อยู่ที่นี่: stackoverflow.com/questions/13180501/…
Eric King

คุณอ่านที่ไหนว่ามันเป็นการปฏิบัติที่ไม่ดี?
Dave Hillier

คำตอบ:


3

1) จริง แต่คุณเปลี่ยน ORM บ่อยแค่ไหน?
2) ฉันจะบอกอย่างนั้นเพราะบริบท ORM เป็นแหล่งเก็บข้อมูลและซ่อนงานจำนวนมากที่เกี่ยวข้องกับการสร้างแบบสอบถามการดึงข้อมูลการทำแผนที่และอื่น ๆ หากคุณไม่ใช้ ORM ตรรกะนั้นก็ยังต้องอยู่ที่ไหนซักแห่ง ฉันไม่รู้ว่านั่นจะมีคุณสมบัติเป็นรูปแบบที่เก็บข้อมูลในความหมายที่เข้มงวดที่สุดของคำว่า ...
3) การสืบค้นแบบสรุปข้อมูลเป็นสิ่งที่ฉันเห็นบ่อยครั้ง แต่นั่นมักจะเป็นการทดสอบ / การขัดถูมากขึ้น นอกเหนือจากนั้นฉันจะระมัดระวังเมื่อใช้การสอบถามซ้ำในส่วนต่าง ๆ ของแอปพลิเคชันเนื่องจากคุณมีความเสี่ยงในการสร้างการพึ่งพาสิ่งที่สามารถเปลี่ยน n-times (n คือจำนวนสถานที่ที่คุณใช้แบบสอบถาม)


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

3
@devnull ฉันไม่เห็นด้วย หากมันเกิดขึ้นมากที่สุดผมจะถือว่ามันเป็นความเสี่ยงที่ยอมรับได้ หากคุณกลัวว่าจะเลือกผิด: ลองทดสอบให้มากขึ้นก่อนที่จะตัดสินใจเลือก ตามทฤษฎีแล้วสิ่งที่เป็นนามธรรมนั้นฟังดูดี แต่ในทางปฏิบัติคุณไขลานส่วนใหญ่ของ api ของออมทั้งหมดเพราะคุณอาจเลิกเลือกอีกสักวันหนึ่ง สำหรับฉันแล้วนั่นคือความพยายามที่สูญเปล่ารหัสซ้ำซ้อนและรหัสอื่น ๆ ที่คุณต้องดูแลและรับประกัน นอกจากนี้การสลับ ORM ไม่ควรส่งผลกระทบต่อทั้งแอปพลิเคชัน เรียนรู้ที่จะวางขอบเขตโดเมน
Stefan Billiet

การเปลี่ยน ORM ไม่ใช่เหตุผลเดียวสำหรับที่เก็บ หากคุณต้องการแนะนำ [แจกจ่าย] แคชในแอปพลิเคชันของคุณ - การเปลี่ยนแปลงทั้งหมดจะทำในที่เก็บและ BL ของคุณจะไม่เปลี่ยนแปลงเนื่องจากการเปลี่ยนแปลงของเลเยอร์การเข้าถึงข้อมูล
Valery

แคชแบบกระจายจะไม่ถูกสร้างไว้ใน ORM ในกรณีส่วนใหญ่
user1450877

ฉันคิดว่ามันขึ้นอยู่กับออม คุณสามารถตัดสินใจใช้ ORM ที่เบากว่า NHibernate หรือ EF
Valery

2

1) คุณจะทำอย่างไรหากคุณต้องการเปลี่ยน ORMs คุณจะมีรหัส ORM เฉพาะในแอปพลิเคชันของคุณหากคุณไม่ได้เก็บไว้ในที่เก็บ

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

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

Company.Product.DataและCompany.Product.Data.EntityFrameworkประกอบ การชุมนุมครั้งแรกจะถูกนำมาใช้อย่างหมดจดสำหรับการเชื่อมต่อเมื่ออื่นจะเป็นการใช้งานที่เป็นรูปธรรมของตรรกะการเข้าถึงข้อมูลของ Entity Framework

2) รูปแบบที่เก็บยังคงใช้ได้เมื่อไม่ใช้ ORM และคุณใช้ ADO.net สำหรับการเข้าถึงข้อมูลและการเติมข้อมูลวัตถุด้วยตัวเอง?

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

ฉันเห็นคลาสที่เก็บข้อมูลที่เริ่มต้นด้วยการมีความรับผิดชอบของ GetAll, GetById, Update และ Delete ซึ่งก็ดี เมื่อโครงการเสร็จสมบูรณ์ชั้นเรียนเดียวกันมีหลายวิธี (ความรับผิดชอบ) ซึ่งไม่ควรมี ตัวอย่างเช่น GetByForename, GetBySurname, UpdateWithExclusions และทุกสิ่งที่บ้าคลั่ง

นี่คือที่มาของคำค้นหาและคำสั่ง

3) ถ้าคุณใช้ ORM แต่ไม่ใช่รูปแบบพื้นที่เก็บข้อมูลคุณจะเก็บแบบสอบถามที่ใช้บ่อย จะเป็นการดีไหมถ้าจะแสดงแต่ละแบบสอบถามเป็นคลาสและมีโรงงานแบบสอบถามบางประเภทเพื่อสร้างอินสแตนซ์

ฉันคิดว่าเป็นความคิดที่ดีมากที่จะใช้คิวรีและคำสั่งแทนที่เก็บ ฉันทำต่อไปนี้:

  • กำหนดอินเทอร์เฟซสำหรับแบบสอบถาม สิ่งนี้จะช่วยให้คุณทดสอบหน่วย เช่นpublic interface IGetProductsByCategoryQuery { ... }

  • กำหนดการใช้งานที่เป็นรูปธรรมสำหรับแบบสอบถาม คุณจะสามารถฉีดสิ่งเหล่านี้ผ่านกรอบ IoC ที่คุณเลือก เช่นpublic class GetProductsByCategoryQuery : IGetProductsByCategoryQuery

ตอนนี้แทนที่จะสร้างที่เก็บข้อมูลที่มีความรับผิดชอบนับสิบฉันก็จัดกลุ่มข้อความค้นหาของฉันเป็นเนมสเปซ ตัวอย่างเช่นอินเทอร์เฟซสำหรับแบบสอบถามด้านบนอาจอาศัยอยู่: Company.SolutionName.Products.Queriesและการใช้งานอาจอยู่ในCompany.SolutionName.Products.Queries.Implementation

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

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


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

1

การปฏิเสธความรับผิด: สิ่งต่อไปนี้ขึ้นอยู่กับความเข้าใจและประสบการณ์โดยย่อของรูปแบบดังกล่าวของฉัน (Repository นั่นคือ) ฉันอาจทำผิด ... อันที่จริงฉันค่อนข้างมั่นใจว่าฉันทำผิด :) ดังนั้นในขณะที่นี่คือความพยายามในการหาคำตอบ แต่ก็เป็นคำถามที่ปลอมตัว

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

ในการตอบคำถามของคุณ:

  1. ไม่ว่าคุณจะชอบหรือไม่การเปลี่ยนแปลงจะเกิดขึ้น และถ้าคุณเขียนแอพพลิเคชั่นและเวลามาเป็นจำนวนมากเพื่อรักษามัน แต่รู้สึกว่าเป็นความเจ็บปวดที่จะทำงานกับ ORM ปัจจุบันและต้องการเปลี่ยนมันคุณจะต้องยกย่องตัวเองในการทำให้เป็นนามธรรม เพียงแค่ใช้สิ่งที่คุณรู้สึกสบายใจไม่ว่าจะเป็น Repository หรือรูปแบบ / แนวคิดอื่น ๆ
  2. ใช่มันเป็นตราบใดที่คุณใช้มันเพื่อแยกการเข้าถึงข้อมูล เช่นเดียวกับที่ฉันกล่าวถึงก่อนหน้านี้คุณสามารถทำให้การใช้งานที่เขียนข้อมูลในไฟล์แบน
  3. ฉันใช้ Repository เพื่อเก็บแบบสอบถามที่ใช้กันทั่วไปและQuery Objectsไว้เมื่อฉันมีแบบสอบถามที่ต้องการปรับแต่ง (ซึ่งไม่มากนัก)

เพื่อเป็นอีกตัวอย่างหนึ่งให้คุณผู้ชายที่ Umbraco แยกบรรจุ DI ออกไปในกรณีที่พวกเขาต้องการเปลี่ยนไปใช้อย่างอื่น


0

ถ้า ORM มีความยืดหยุ่นของ LINQ อยากโหลด ฯลฯ ฉันจะไม่ซ่อนมันไว้ข้างหลังเลเยอร์พิเศษใด ๆ
ถ้ามันเกี่ยวข้องกับ raw sql (micro ORM) ดังนั้นควรใช้ "method per query" ต่อไปเพื่อให้สามารถนำกลับมาใช้ใหม่ได้

What do you do if you want to switch out ORMs? 
You would have ORM specific code in your application if you do not contain it in a repository.

ทำไมคุณต้องเปลี่ยน
ควรใช้คุณสมบัติส่วนใหญ่ที่คุณต้องการ เป็นไปได้ว่า ormX รุ่นใหม่จะนำคุณสมบัติใหม่มาใช้และดีกว่ารุ่นปัจจุบัน แต่ ...
หากคุณเลือกที่จะซ่อน orm คุณสามารถใช้คุณสมบัติที่ผู้สมัครทุกคนมีเหมือนกันเท่านั้น
เช่นคุณไม่สามารถใช้Dictionary<string, Entity>คุณสมบัติในเอนทิตีของคุณได้เนื่องจาก ormY ไม่สามารถจัดการคุณสมบัติเหล่านั้นได้

สมมติว่าใช้ LINQ ส่วนใหญ่ของ orm switch เป็นเพียงการสลับการอ้างอิงไลบรารีและแทนที่session.Query<Foo>()ด้วยcontext.Foosหรือคล้ายกันจนกว่าจะรวบรวม งานที่น่าเบื่อ แต่ใช้เวลาน้อยกว่าการเข้ารหัสเลเยอร์สิ่งที่เป็นนามธรรม

Is the repository pattern still valid when not using an ORM and you are using ADO.NET for data access and populating object data yourself?

ใช่. รหัสควรจะนำมาใช้ซ้ำได้และนั่นหมายถึงการวางอาคาร sql วัตถุเป็นวัตถุ ฯลฯ ในที่เดียว (แยกชั้น) คุณอาจเรียกคลาส "XRepository" และแยกอินเทอร์เฟซออกจากคลาสได้

If you use an ORM but not the repository pattern where do you keep commonly used queries? 
Would it be wise to represent each query as a class and have some sort of query factory to create instances?

สมมติว่า LINQ ถูกใช้คลาส wrapper จะ overkill IMHO วิธีที่ดีกว่าจะเป็นวิธีการขยาย

public static IQueryable<T> Published<T>(this IQueryable<T> source) where T : Page
{
    // at some point someone is going to forget to check that status
    // so it makes sense to extract this thing
    return source.Where(x => x.Status == Status.Published && x.PublishTime <= DateTime.UtcNow);
}

รหัสใด ๆ ที่ใช้ในหลาย ๆ สถานที่ (หรือมีศักยภาพ) และมีความซับซ้อนเพียงพอ (เกิดข้อผิดพลาดได้ง่าย) ควรถูกแยกไปยังที่ส่วนกลาง

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