วิธีที่ดีที่สุดในการเชื่อมโยงบริบทฐานข้อมูล Entity Framework (รุ่น) กับ ViewModel ใน MVVM WPF คืออะไร


9

ดังในคำถามข้างต้น: อะไรคือวิธีที่ดีที่สุดในการเชื่อมโยงโมเดลฐานข้อมูล Entity Framework (บริบท) กับ viewModel ใน MVVM (WPF)

ฉันกำลังเรียนรู้รูปแบบ MVVM ใน WPF ตัวอย่างจำนวนมากแสดงวิธีการนำโมเดลไปใช้กับ viewModel แต่โมเดลในตัวอย่างนั้นเป็นคลาสที่เรียบง่ายฉันต้องการใช้ MVVM พร้อมกับโมเดลเฟรมเวิร์กเอนทิตี (base first approach) Whats วิธีที่ดีที่สุดในการวางสายเพื่อดู model

ขอบคุณสำหรับคำตอบ

//ctor of ViewModel 
public ViewModel()
{ 
db = new PackageShipmentDBEntities(); // Entity Framework generated class

ListaZBazy = new ObservableCollection<Pack>(db.Packs.Where(w => w.IsSent == false)); 
}

นี่คือ ctor ตามปกติของ ViewModel คิดว่ามีวิธีที่ดีกว่าฉันอ่านเกี่ยวกับรูปแบบของที่เก็บไม่แน่ใจว่าฉันสามารถปรับใช้กับ WPF MVVM ได้หรือไม่

คำตอบ:


4

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

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

  1. สร้างโครงการแยกต่างหากสำหรับ EDMX เพื่อทำหน้าที่เป็นเลเยอร์การเข้าถึงข้อมูลของคุณ
  2. สร้างโฟลเดอร์ "Repositories" ภายใต้โครงการเดียวกัน
  3. สร้างคลาสพื้นฐาน "BaseRepository" เพื่อทำหน้าที่เป็น "หน่วยงาน" IDisposableจะอนุญาตให้คุณใช้สิ่งนี้ในusing(){}และpartialจะอนุญาตให้คุณใช้ที่เก็บอื่น ๆ

    public partial class MyEntityRepository : IDisposable
    {
        MyEntities context = new MyEntities();
    
        public void Dispose()
        {
            context.Dispose();
        }
    }
    
  4. สร้างไฟล์อื่นที่ชื่อว่า "MyOtherRepository" สร้างคลาสบางส่วนที่เหมือนกัน แต่ใช้วิธีการตามสิ่งที่คุณต้องการให้ไฟล์นั้นมี

    public partial class MyEntityRepository
    {
        public void MyOtherMethodSave(EntityObject obj)
        {
            //work with context
            ...
    
            context.SaveChanges();
        }
    }
    

ใน VM ของคุณคุณสามารถทำได้ ...

using(MyEntityRepository repo = new MyEntityRepository())
{
     repo.MyOtherMethodSave(objectToSave);
}

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

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


2
คุณสามารถแทนที่ 'MyEntityRepository' บริบทของ EF และคุณจะได้รับผลลัพธ์เดียวกัน นอกจากว่าคุณต้องการล้อมบริบทของ EF ด้วย "พื้นที่เก็บข้อมูล" ของคุณเองเพิ่มการทำซ้ำ
ร่าเริง

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

4

ตรงข้ามกับที่เก็บซึ่งฉันไม่ชอบ ฉันจะแนะนำให้ใช้รูปแบบคำสั่งตามคำแนะนำของAyende

เพียงกล่าวว่าสำหรับการดำเนินการแต่ละครั้งคุณจะสร้างThisOperationCommandคลาสแยกต่างหาก ในชั้นเรียนนี้คุณจะได้ทำงานกับบริบทของ EF คุณอาจใช้คลาสพื้นฐานEFCommandที่ใช้ระบบประปาให้คุณ

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

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


0

สำหรับสถานการณ์อย่างง่ายฉันได้ใช้สิ่งต่อไปนี้:

public class ViewModel : IDisposable {

    private EntitiesContext _context = new EntitiesContext();

    private SomeEntity _model;
    public SomeEntity Model {
       get { return _model; }
    }

    public View(int id) {
        _model = _context.SomeEntity.Find(id);
    }

    private ICommand _saveCommand = new RelayCommand(() => _context.SaveChanges());
    public ICommand SaveCommand {
        get { return _saveCommand; }
    }        

    public void Dispose() {
         _context.Dispose();
    }

}

1
ปัญหาของเรื่องนี้ก็คือบริบทของคุณอาจจะ "อยู่ได้นาน"
รองเท้า

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