ทำไมฉันไม่ควรใช้รูปแบบพื้นที่เก็บข้อมูลกับ Entity Framework?


203

ในระหว่างการสัมภาษณ์งานฉันถูกขอให้อธิบายว่าทำไมรูปแบบที่เก็บไม่ใช่รูปแบบที่ดีในการทำงานกับ ORMs เช่น Entity Framework เหตุใดจึงเป็นเช่นนี้


60
มันเป็นคำถามที่หลอกลวง
Omu

2
ฉันอาจตอบผู้สัมภาษณ์ว่า Microsoft ใช้รูปแบบที่เก็บบ่อยมากในขณะที่พวกเขาแสดงให้เห็นถึงกรอบงานเอนทิตี: | .
Laurent Bourgault-Roy

1
แล้วอะไรคือเหตุผลของผู้สัมภาษณ์ที่ไม่ใช่ความคิดที่ดี?
บ๊อบฮอร์น

3
ข้อเท็จจริงที่ตลกคือการค้นหา "รูปแบบพื้นที่เก็บข้อมูล" ใน Google ให้ผลลัพธ์ที่เกี่ยวข้องกับ Entity Framework เป็นส่วนใหญ่และวิธีการใช้รูปแบบกับ EF
Arseni Mourzenko

2
ตรวจสอบบล็อก Ayende ของayende.com/blog จากสิ่งที่ฉันรู้เขาเคยใช้รูปแบบของที่เก็บ แต่ในที่สุดก็ยอมแพ้ในรูปแบบของ Query Object Pattern
Jaime Sangcap

คำตอบ:


99

ฉันไม่เห็นเหตุผลใด ๆ ที่รูปแบบ Repository จะไม่ทำงานกับ Entity Framework รูปแบบพื้นที่เก็บข้อมูลเป็นชั้นนามธรรมที่คุณใส่ในชั้นการเข้าถึงข้อมูลของคุณ ชั้นการเข้าถึงข้อมูลของคุณสามารถเป็นอะไรก็ได้ตั้งแต่ขั้นตอนการเก็บ ADO.NET บริสุทธิ์ไปจนถึง Entity Framework หรือไฟล์ XML

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

ฉันใช้รูปแบบพื้นที่เก็บข้อมูลกับ Entity Framework เป็นวิธีการเข้าถึงชั้นข้อมูลของฉันและยังพบปัญหา

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

public interface IRepository
{
  IEnumerable<CustomerDto> GetCustomers();
}
public EFRepository : IRepository
{
  private YourDbContext db;
  private EFRepository()
  {
    db = new YourDbContext();
  }
  public IEnumerable<CustomerDto> GetCustomers()
  {
    return db.Customers.Select(f=>new CustomerDto { Id=f.Id, Name =f.Name}).ToList();
  }
}
public MockRepository : IRepository
{
  public IEnumerable<CustomerDto> GetCustomers()
  {
    // to do : return a mock list of Customers
    // Or you may even use a mocking framework like Moq
  }
}

ตอนนี้ใช้ DI คุณจะได้รับการติดตั้ง

public class SomeService
{
  IRepository repo;
  public SomeService(IRepository repo)
  {
     this.repo = repo;
  }  
  public void SomeMethod()
  {
    //use this.repo as needed
  }    
}

3
ฉันไม่ได้บอกว่ามันจะไม่ทำงานฉันยังทำงานกับรูปแบบพื้นที่เก็บข้อมูลกับ EF แต่วันนี้ฉันถูกถามว่าทำไมมันไม่ดีที่จะใช้รูปแบบกับ DataBase แอปพลิเคชันที่ใช้ฐานข้อมูล

2
ตกลงเนื่องจากนี่เป็นคำตอบที่ได้รับความนิยมมากที่สุดฉันจะเลือกให้เป็นคำตอบที่ถูกต้อง

65
เมื่อครั้งสุดท้ายที่เป็นที่นิยมมากที่สุด == ถูกต้อง?
HDave

14
DbContext เป็นที่เก็บอยู่แล้วพื้นที่เก็บข้อมูลนั้นมีความหมายว่าเป็นสิ่งที่เป็นนามธรรมในระดับต่ำ หากคุณต้องการให้แหล่งข้อมูลที่แตกต่างเป็นนามธรรมสร้างวัตถุเพื่อแสดงสิ่งเหล่านั้น
Daniel Little

7
ColacX เราลองแค่นั้น - DBcontext ในเลเยอร์คอนโทรลเลอร์ - และเรากลับสู่รูปแบบ repo ด้วยรูปแบบ Repo การทดสอบหน่วยเริ่มต้นจากการเยาะเย้ย DbContext ขนาดใหญ่ที่ล้มเหลวอย่างต่อเนื่อง EF เป็นเรื่องยากที่จะใช้และเปราะบางและใช้เวลานานในการวิจัยสำหรับความแตกต่างของ EF ตอนนี้เรามี mocks เรียบง่ายขนาดเล็กของ repo รหัสสะอาดกว่า การแยกงานชัดเจนขึ้น ฉันไม่เห็นด้วยกับฝูงชนที่ EF เป็นรูปแบบซื้อคืนและหน่วยทดสอบแล้ว
Rhyous

434

เหตุผลเดียวที่ดีที่สุดที่จะไม่ใช้รูปแบบพื้นที่เก็บข้อมูลกับ Entity Framework? Entity Framework แล้วดำเนินการรูปแบบการเก็บข้อมูล DbContextคือ UoW ของคุณ (หน่วยงาน) และDbSetที่เก็บคือ การนำเลเยอร์อื่นไปใช้งานด้านบนนี้ไม่เพียง แต่ซ้ำซ้อนเท่านั้น แต่ยังทำให้การบำรุงรักษาทำได้ยากขึ้น

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

อย่างไรก็ตามมันไม่ใช่ความคิดที่ดีที่จะสร้างสิ่งที่เป็นนามธรรมด้านบน ORM ของคุณไม่ใช่แค่สิ่งที่ซับซ้อนเท่ากับ UoW / repostitory ฉันจะไปกับรูปแบบการบริการที่คุณสร้าง API ที่แอปพลิเคชันของคุณสามารถใช้โดยไม่ทราบหรือไม่สนใจว่าข้อมูลนั้นมาจาก Entity Framework, NHibernate หรือ Web API สิ่งนี้ง่ายกว่ามากเนื่องจากคุณเพียงเพิ่มวิธีในคลาสบริการของคุณเพื่อส่งคืนข้อมูลที่แอปพลิเคชันของคุณต้องการ หากคุณกำลังเขียนแอปที่ต้องทำตัวอย่างเช่นคุณอาจได้รับบริการโทรกลับรายการที่ถึงกำหนดส่งในสัปดาห์นี้และยังไม่เสร็จสมบูรณ์ แอปทั้งหมดของคุณรู้ว่าถ้ามันต้องการข้อมูลนี้มันจะเรียกวิธีการนั้น ในวิธีการนี้และในบริการของคุณโดยทั่วไปคุณจะต้องโต้ตอบกับ Entity Framework หรืออะไรก็ตามที่คุณใช้ จากนั้นหากคุณตัดสินใจเปลี่ยน ORM ในภายหลังหรือดึงข้อมูลจาก Web API

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


68
นี่ดูเหมือนจะเป็นคำตอบที่ถูกต้องเท่านั้น
Mike Chamberlain

10
คุณสามารถเยาะเย้ยDbContextใน EF6 + (ดู: msdn.microsoft.com/en-us/data/dn314429.aspx ) แม้แต่ในรุ่นที่น้อยกว่าคุณสามารถใช้DbContextคลาสที่เหมือนของปลอมกับ mocked DbSets ได้เนื่องจากDbSetใช้ตัววนIDbSetซ้ำ
Chris Pratt

14
@TheZenker คุณอาจไม่ได้ติดตามรูปแบบที่เก็บข้อมูลอย่างแน่นอน ความแตกต่างที่เข้มงวดที่สุดคือค่าส่งคืน ที่เก็บส่งคืนเคียวรีขณะที่เซอร์วิสควรส่งคืนจำนวนที่นับได้ แม้ว่าจะไม่ใช่ขาวดำจริง ๆ เพราะมีบางอย่างทับซ้อนกัน มันมีมากขึ้นในวิธีที่คุณใช้ ที่เก็บควรส่งคืนชุดของวัตถุทั้งหมดซึ่งคุณจะต้องสอบถามเพิ่มเติมในขณะที่บริการควรส่งคืนชุดข้อมูลสุดท้ายและไม่ควรสนับสนุนการสืบค้นเพิ่มเติม
Chris Pratt

10
ความเสี่ยงของการพูดถึงเรื่องอื้อฉาว: พวกมันผิด ตอนนี้เท่าที่บทเรียนอย่างเป็นทางการไปแล้ว Microsoft ได้สำรองข้อมูลโดยใช้ที่เก็บจากสิ่งที่ฉันเห็นตั้งแต่ EF6 เกี่ยวกับหนังสือฉันไม่สามารถพูดได้ว่าทำไมผู้เขียนเลือกใช้ที่เก็บ สิ่งที่ฉันสามารถพูดได้ในฐานะคนในร่องลึกที่สร้างแอพพลิเคชั่นขนาดใหญ่คือการใช้รูปแบบพื้นที่เก็บข้อมูลกับ Entity Framework เป็นฝันร้ายของการบำรุงรักษา เมื่อคุณย้ายไปสู่สิ่งที่ซับซ้อนกว่าที่เก็บข้อมูลจำนวนหนึ่งคุณจะต้องเสียเวลาจำนวนมากในการจัดการที่เก็บข้อมูล / หน่วยงานของคุณ
Chris Pratt

6
ฉันมักจะมีเพียงหนึ่งบริการต่อฐานข้อมูลหรือวิธีการเข้าถึง ฉันใช้วิธีการทั่วไปเพื่อสอบถามเอนทิตีหลายประเภทจากชุดวิธีการเดียวกัน ฉันใช้ Ninject เพื่อแทรกบริบทของฉันลงในบริการของฉันและจากนั้นบริการของฉันเป็นตัวควบคุมของฉันดังนั้นทุกอย่างเรียบร้อยและเป็นระเบียบ
Chris Pratt

45

นี่คือสิ่งหนึ่งที่นำมาจาก Ayende Rahien: สถาปัตย์ในหลุมแห่งความพินาศ: ความชั่วร้ายของเลเยอร์สิ่งที่เป็นนามธรรม

ฉันยังไม่แน่ใจว่าฉันเห็นด้วยกับข้อสรุปของเขาหรือไม่ มันเป็น catch-22 - ในอีกด้านหนึ่งถ้าฉันใส่เนื้อหาบริบทของ EF ลงในที่เก็บชนิดเฉพาะด้วยวิธีการดึงข้อมูลเฉพาะแบบสอบถามฉันจริง ๆ แล้วฉันสามารถทดสอบหน่วยของฉัน (เรียงลำดับ) ซึ่งเกือบเป็นไปไม่ได้กับ Entity กรอบงานเพียงอย่างเดียว ในทางกลับกันฉันสูญเสียความสามารถในการทำแบบสอบถามที่หลากหลายและการบำรุงรักษาความสัมพันธ์แบบ semantic (แม้ว่าฉันจะสามารถเข้าถึงคุณลักษณะเหล่านั้นได้อย่างเต็มที่ฉันมักจะรู้สึกว่าฉันกำลังเดินอยู่บนเปลือกไข่รอบ ๆ EF หรือ ORM อื่น ๆ เนื่องจากฉันไม่เคยรู้ว่าวิธีการใช้งานแบบ IQueryable นั้นอาจจะสนับสนุนหรือไม่ก็ตามไม่ว่ามันจะตีความการเพิ่มของฉันไปยังคอลเลกชันคุณสมบัติการนำทางเป็นการสร้างหรือเพียงแค่การเชื่อมโยงไม่ว่ามันจะขี้เกียจหรือกระตือรือร้นหรือไม่โหลดเลย ค่าเริ่มต้น ฯลฯ ดังนั้นนี่อาจเป็นการดีกว่า "การแมป" ที่ไม่มีอิมพีแดนซ์เป็นวัตถุเชิงวัตถุเป็นสิ่งมีชีวิตในตำนาน - นั่นอาจเป็นสาเหตุว่าทำไม Entity Framework รุ่นล่าสุดจึงมีชื่อรหัสว่า "Magic Unicorn")

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

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

อัปเดต:ฉันประสบความสำเร็จในการใช้ผู้ให้บริการความพยายามสำหรับ Entity Framework ความพยายามเป็นผู้ให้บริการในหน่วยความจำ (โอเพ่นซอร์ส) ที่ให้คุณใช้ EF ในการทดสอบอย่างที่คุณจะใช้กับฐานข้อมูลจริง ฉันกำลังพิจารณาเปลี่ยนการทดสอบทั้งหมดในโครงการนี้ฉันกำลังทำงานเพื่อใช้ผู้ให้บริการนี้เนื่องจากดูเหมือนว่าจะทำให้สิ่งต่าง ๆ ง่ายขึ้นมาก มันเป็นทางออกเดียวที่ฉันค้นพบจนถึงตอนนี้ที่จัดการกับปัญหาทั้งหมดที่ฉันคุยโวเกี่ยวกับเรื่องก่อนหน้านี้ สิ่งเดียวที่มีความล่าช้าเล็กน้อยเมื่อเริ่มต้นการทดสอบของฉันเนื่องจากกำลังสร้างฐานข้อมูลในหน่วยความจำ (ใช้แพ็คเกจอื่นที่เรียกว่า NMemory เพื่อทำสิ่งนี้) แต่ฉันไม่เห็นว่านี่เป็นปัญหาจริง มีบทความของCode Projectที่พูดถึงการใช้ความพยายาม (กับ SQL CE) สำหรับการทดสอบ


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

3
คุณยังคงสามารถทำการทดสอบหน่วยโดยไม่ต้องล้อมบริบท EF (ซึ่งเป็นที่เก็บข้อมูลอยู่แล้ว) คุณควรทดสอบหน่วยโดเมน / บริการของคุณไม่ใช่การสืบค้นฐานข้อมูล (เป็นการทดสอบการรวมระบบ)
Daniel Little

2
ความสามารถในการทดสอบของ EF นั้นพัฒนาขึ้นอย่างมากในเวอร์ชัน 6 ตอนนี้คุณอาจเยาะเย้ยDbContextได้ ไม่ว่าคุณจะล้อเลียนอยู่ตลอดDbSetและนั่นก็เป็นส่วนสำคัญของ Entity Framework อยู่แล้ว DbContextน้อยกว่าชั้นเรียนที่จะDbSetเก็บคุณสมบัติของคุณ(ที่เก็บข้อมูล) ไว้ในที่เดียว (หน่วยของงาน) โดยเฉพาะอย่างยิ่งในบริบทการทดสอบหน่วยที่การเตรียมใช้งานฐานข้อมูลและการเชื่อมต่อทั้งหมดนั้นไม่ต้องการหรือจำเป็น
Chris Pratt

การนำทางเอนทิตีที่เกี่ยวข้องกับการสูญเสียไปนั้นไม่ดีและเป็นตัวนับ OOP แต่คุณจะสามารถควบคุมสิ่งที่ถูกสอบถามได้มากขึ้น
Alireza

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

16

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


คุณสามารถบอกข้อดีบางอย่างสำหรับ "Entity Framework ที่ให้ประโยชน์การเข้ารหัสและประโยชน์การทำงาน" ได้หรือไม่?
ManirajSS

2
นี่คือสิ่งที่เขาหมายถึง var id = Entity.Where (i => i.Id == 1337) .Single () ห่อหุ้มและห่อสิ่งนี้ในพื้นที่เก็บข้อมูลโดยทั่วไปคุณไม่สามารถทำตรรกะแบบสอบถามแบบนี้จากภายนอกซึ่งบังคับให้คุณเพิ่มรหัสอีก ที่เก็บและอินเตอร์เฟสสำหรับดึง ID B ส่งคืนเอนทิตีบริบทจากที่เก็บเพื่อให้คุณสามารถเขียนตรรกะการสืบค้น (ซึ่งไร้สาระ)
ColacX

14

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

พิจารณารูปแบบพื้นที่เก็บข้อมูลอีกครั้ง


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

1
ในขณะที่ฉันคิดว่ามันเป็นเรื่องจริงสำหรับเช่น NHibernate ( ISessionFactoryและISessionเยาะเย้ยได้อย่างง่ายดาย) มันไม่ง่ายอย่างนั้นด้วยDbContextโชคไม่ดี ...
Patryk Ćwiek

6

เหตุผลที่ดีมากในการใช้รูปแบบพื้นที่เก็บข้อมูลคือการอนุญาตให้แยกตรรกะทางธุรกิจและ / หรือ UI ของคุณจาก System.Data.Entity มีข้อดีหลายข้อในเรื่องนี้รวมถึงประโยชน์ที่แท้จริงในการทดสอบหน่วยโดยอนุญาตให้เขาใช้ Fakes หรือ Mocks


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

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

1
จริง ๆ แล้วฉันเริ่มตั้งคำถามกับความคิดเห็นก่อนหน้านี้เกี่ยวกับเรื่องนี้ EF เป็นรูปแบบหน่วยการทำงานและที่เก็บข้อมูลแบบรวม ดังที่ Chris Pratt กล่าวถึงข้างต้นด้วย EF6 คุณสามารถเยาะเย้ยวัตถุ Context และ DbSet ได้อย่างง่ายดาย ฉันยังเชื่อว่าการเข้าถึงข้อมูลควรถูกห่อไว้ในชั้นเรียนเพื่อป้องกันคลาสตรรกะทางธุรกิจจากกลไกการเข้าถึงข้อมูลจริง แต่เพื่อไปที่ทั้งหมูและห่อ EF ด้วยพื้นที่เก็บข้อมูลอื่นและหน่วยงานที่เป็นนามธรรมดูเหมือนว่าจะเกินขีด
James Culshaw

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

@jcmcbeth หากคุณดูความคิดเห็นของฉันโดยตรงเหนือคุณจะเห็นว่าฉันได้เปลี่ยนความคิดเห็นดั้งเดิมของฉันด้วยรูปแบบที่เก็บและ EF
James Culshaw

0

เรามีปัญหากับอินสแตนซ์ DbContext Entity Framework ที่ซ้ำกัน แต่แตกต่างกันเมื่อคอนเทนเนอร์ IoC ที่ใหม่ () ขึ้นที่เก็บต่อประเภท (ตัวอย่างเช่น UserRepository และอินสแตนซ์ GroupRepository ที่แต่ละครั้งเรียก IDbSet ของตนเองจาก DBContext) บางครั้งอาจทำให้บริบทหลายรายการต่อคำขอ (ในบริบทของ MVC / เว็บ)

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


ฉันพบปัญหานี้ในหลาย ๆ โครงการ
ColacX

0

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

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

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

ฉันคิดว่าเฟรมเวิร์กเอนทิตีใช้รูปแบบที่เก็บได้ดีกว่าบทความใด ๆ ที่ฉันได้อ่านมาและมันไปไกลเกินกว่าที่พวกเขาพยายามจะทำ

พื้นที่เก็บข้อมูลเป็นแนวปฏิบัติที่ดีที่สุดในสมัยนั้นที่เราใช้ XBase, AdoX และ Ado.Net แต่ใช้เอนทิตี้ !! (พื้นที่เก็บข้อมูลบนพื้นที่เก็บข้อมูล)

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


1
ยกเว้นว่าคุณไม่ต้องการทดสอบพฤติกรรมฐานข้อมูลของคุณในการทดสอบหน่วยเนื่องจากไม่ใช่ระดับการทดสอบอย่างสมบูรณ์
Mariusz Jamro

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

-3

มันเกิดจากการโยกย้าย: มันเป็นไปไม่ได้ที่จะได้รับการโยกย้ายในการทำงานเพราะสตริงการเชื่อมต่ออยู่ใน web.config แต่ DbContext อยู่ในเลเยอร์พื้นที่เก็บข้อมูล IDbContextFactory จำเป็นต้องมีสตริงการกำหนดค่าไปยังฐานข้อมูล แต่ไม่มีวิธีใดที่การย้ายข้อมูลจะได้รับสตริงการเชื่อมต่อจาก web.config

มีวิธีแก้ไขอยู่บ้าง แต่ฉันยังไม่พบวิธีแก้ปัญหาที่ดีสำหรับเรื่องนี้!

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