简体   繁体   English

使用WPF的实体框架存储库模式

[英]Entity Framework Repository Pattern with WPF

I have watched Mosh Hamedani's course on EF as well as read articles on MSDN. 我看过Mosh Hamedani关于EF的课程以及阅读有关MSDN的文章。 I have also read a few discussions here in StackOverflow over this. 我还在StackOverflow中阅读了一些讨论。 But I cannot still understand it properly. 但我还是不能理解它。

I am trying to use Entity Framework with repository pattern in WPF. 我试图在WPF中使用Entity Framework和存储库模式。 Now, everywhere I see people using repository pattern in such a way that it returns a IEnumerable<> of items. 现在,在任何地方,我都看到人们使用存储库模式,以便返回IEnumerable <>项。 However, since I am trying to bind these to datagrids which needs to be updated, is it not better to return ObservableCollection? 但是,由于我试图将这些绑定到需要更新的数据网格,因此返回ObservableCollection不是更好吗?

Also, I watched a few tutorials where they blindly remove and replace ICollection and Hashset in the entities created by EF with ObservableCollection. 另外,我观察了一些教程,他们盲目地删除并替换了EF和ObservableCollection创建的实体中的ICollection和Hashset。 However, there is a tutorial where it says, and I quote, "Find and replace the first occurrence of “HashSet” with “ObservableCollection”. This occurrence is located approximately at line 50. Do not replace the second occurrence of HashSet found later in the code." 但是, 一个教程,它说,并且我引用“查找并用”ObservableCollection“替换第一次出现的”HashSet“。这个事件大约位于第50行。不要替换后面发现的第二次出现的HashSet编码。” It does not even explain why I shouldn't replace the second occurrence at all. 它甚至没有解释为什么我根本不应该替换第二次出现。

Can anyone tell me how to understand which ICollection and Hashset are safe to be replaced with ObservableCollection? 任何人都可以告诉我如何理解哪个ICollection和Hashset可以安全地替换为ObservableCollection?

As a side note, I have introduced INotifyPropertyChanged in Entities. 作为旁注,我在实体中引入了INotifyPropertyChanged。 Is it better practice to use ObservableObject? 使用ObservableObject是更好的做法吗?

Any help would be genuinely welcome. 真的欢迎任何帮助。

The best practices suggest to segregate all the responsibilities, ideally once per class. 最佳实践建议将所有职责分开,最好每班一次。 There is no reason that a contract of a repository pattern returns a collection of type ObservableCollection<> . 没有理由存储库模式的契约返回ObservableCollection<>类型的集合。 This is not needed and add unnecessary overheads. 这不是必需的,并增加了不必要的开销。

To properly bind an UI element to your repository pattern and updates the data source accordingly, we are introducing another responsibility: the coordination of the update of the data. 为了将UI元素正确绑定到存储库模式并相应地更新数据源,我们引入了另一个职责:协调数据更新。 You can typically implement this responsibility using the MVVM pattern, where your view model expose your initial IEnumerable<> collection to an ObservableCollection<> to your view and call your repository when updates are triggered. 您通常可以使用MVVM模式实现此职责,其中视图模型将您的初始IEnumerable<>集合暴露给您的视图的ObservableCollection<> ,并在触发更新时调用您的存储库。

Thus, the workflow to load data becomes: 因此,加载数据的工作流程变为:

Repository( IEnumerable<> ) --[LOAD]--> ViewModel( ObservableCollection<> ) --> View 存储库( IEnumerable<> ) - [LOAD] - > ViewModel( ObservableCollection<> ) - >查看

and the workflow to update data becomes: 并且更新数据的工作流程变为:

View --[UPDATE]--> ViewModel --[PROPAGATE]--> Repository 查看 - [更新] - > ViewModel - [PROPAGATE] - >存储库

The view model takes care of the ObservableCollection<> which is a need of the UI layer and calls the right method(s) of your repository (for example repo.Save(myItem) ) to keep the data source updated. 视图模型负责处理ObservableCollection<> ,它需要UI层并调用存储库的正确方法(例如repo.Save(myItem) )以保持数据源的更新。

You got confused because you wish to use in one hand the repository pattern, that should introduce a notion of abstraction (the implementation can be replaced by anything) and the Microsoft guide, that suggests to implement a strong coupling between your data and UI layers. 您感到困惑,因为您希望一方面使用存储库模式,它应该引入一个抽象概念(实现可以被任何东西替换)和Microsoft指南,它建议实现数据和UI层之间的强耦合。

The bottom line here is either you go with what Microsoft suggest with a strong coupling, or with a loosely coupled solution using a repository pattern. 这里的底线要么是微软建议的强耦合,要么是使用存储库模式的松散耦合解决方案。 Nonetheless, if you try to do the both at the same time, you are going to end up with a leaky abstraction and only get the drawbacks of the two solutions. 尽管如此,如果你试图同时做这两者,你最终会得到一个漏洞抽象,只能得到两个解决方案的缺点。


EDIT to suggest a contract for the repository. 编辑以建议存储库的合同。

public interface ItemsRepository
{
   IEnumerable<Item> GetAll();
   void Update(Item item);
}

Then, the UI layer will only reference this interface to interact with your database. 然后,UI层将仅引用此接口以与您的数据库进行交互。 You can now implement it with any ORM library or why not a web service if you suddently need to. 您现在可以使用任何ORM库实现它,或者如果您突然需要,为什么不能使用Web服务。

What you need is to decouple your UI from your data layer. 您需要的是将UI与数据层分离。
The repository is responsible for managing you data access code (read/write to the db) 存储库负责管理您的数据访问代码(读/写数据库)

Now,how you display and edit your data on the UI is not the repository's problem. 现在,如何在UI上显示和编辑数据不是存储库的问题。
You need a business/presentation layer. 您需要一个业务/表示层。

For example,if you have a CustomerRepository like 例如,如果您有CustomerRepository之类的

class CustomerRepository
{
    public IEnumerable<Customer> GetCustomers()
    {
         return yourContext.Customers.ToList();
    }
}

You can create a service like 你可以创建一个像这样的服务

class CustomerService
{
    public ObservableCollectionOf<Customer> GetCustomers()
    {
         var customers=new CustomerRepository().GetCustomers().OrderBy...;
         return new ObservableCollectionOf(customers);
    }
}

You don't have to ,and probably shouldn't ,use UI(InotifyPropertyChanged,Observables) related code on you Entities. 您不必,也可能不应该在您的实体上使用UI(InotifyPropertyChanged,Observables)相关代码。

Create ViewModels (in your Business/Presentation Layer) which are responsible for that 创建负责该操作的ViewModel(在您的业务/表示层中)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM