wpf 带有实体框架的 MVVM 模型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25726804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:30:07  来源:igfitidea点击:

MVVM Model with Entity Framework

c#wpfentity-frameworkmvvm

提问by Danilo Breda

I have a Prototype using WPF + MVVM + PRISM + ENTITY FRAMEWORK

我有一个使用 WPF + MVVM + PRISM + ENTITY FRAMEWORK 的原型

The problem is that im very confuse if i use the ENTITY FRAMEWORK Entities as the Model of the MVVM pattern. I have a Business Logic Layer, and i had problems using mappers on this layer, because im very unhappy on the conversion (Map problem).

问题是,如果我使用实体框架实体作为 MVVM 模式的模型,我会非常困惑。我有一个业务逻辑层,我在这一层上使用映射器时遇到了问题,因为我对转换非常不满意(映射问题)。

What i can do to simplify the code, use a real Model not the Entitie object(for me use the Entitie as model is incorrect on the frontend), with the MVVM pattern on mind... and stay good for changes on the future, it will have 200+ entities on the final version...

我可以做些什么来简化代码,使用真正的模型而不是 Entitie 对象(对我而言,使用 Entitie 作为模型在前端是不正确的),考虑到 MVVM 模式......并保持良好的未来变化,最终版本将有 200 多个实体...

Thats my layers...(Please forget about Mapping, since i taked it off putting the EF entities on the ViewModel, but the image represents the correct layers)

那就是我的层...(请忘记映射,因为我将 EF 实体放在 ViewModel 上,但图像代表了正确的层)

Im not using the repository too since i can add it on the end with changes only on the BLL.

我也没有使用存储库,因为我可以将它添加到最后,只在 BLL 上进行更改。

My layers

我的图层

VIEW MODEL:my current prototype do a getall, put it on a grid, and on selectchanged of the grid i put selected item on the textbox, and the save button update this changes to the database.

查看模型:我当前的原型做一个 getall,把它放在一个网格上,在网格的 selectchanged 上我把选定的项目放在文本框上,然后保存按钮将这个更改更新到数据库中。

public class CadastroClienteViewModel : BindableBase, ICadastroClienteViewModel
{
    private readonly IClienteBLL _clienteService;

    #region Model
    //public Cliente ObCliente { get; private set; }

    public int ClienteID
    {
        get { return ((Cliente)cliItems.CurrentItem).ClienteID; }
        set
        {
            ((Cliente)cliItems.CurrentItem).ClienteID = value;
            OnPropertyChanged("ClienteID");
        }
    }

    public string Nome
    {
        get { return ((Cliente)cliItems.CurrentItem).Nome; }
        set
        {
            ((Cliente)cliItems.CurrentItem).Nome = value;
            OnPropertyChanged("Nome");
        }
    }

    #endregion

    public CadastroClienteViewModel(IClienteBLL ServiceCliente)
    {
        //ObCliente = new Cliente();
        _clienteService = ServiceCliente;

        this.SaveCommand = new DelegateCommand(ExecuteMethodSave);
        this.RefreshCommand = new DelegateCommand(ExecuteMethodRefresh, CanExecuteMethodRefresh);
        RefreshCommand.Execute(null);
    }

    private void ExecuteMethodSave()
    {
        _clienteService.ClienteBLL_Update(((Cliente)cliItems.CurrentItem));

        RefreshCommand.Execute(null);
    }

    private bool CanExecuteMethodRefresh()
    {
        return true;
    }

    private void ExecuteMethodRefresh()
    {
        var personViewModels = _clienteService.ClienteBLL_GetAll();

        //cliente = new ObservableCollection<Cliente>(personViewModels);

        cliItems = new ListCollectionView(personViewModels.ToList());
        cliItems.CurrentChanged += CliItemsOnCurrentChanged;

        //OnPropertyChanged("cliente");
        OnPropertyChanged("cliItems");
    }

    private void CliItemsOnCurrentChanged(object sender, EventArgs eventArgs)
    {
        //OnPropertyChanged("ObCliente");
    }

    public ICommand SaveCommand { get; private set; }
    public ICommand RefreshCommand { get; private set; }

    //public ObservableCollection<Cliente> cliente { get; private set; }
    public ICollectionView cliItems { get; private set; }
}

MODEL(Im not using it... but i would like):

模型(我不使用它......但我想要):

public class MCliente
{
    public int ClienteID { get; set; }
    public string Nome { get; set; }
}

EF Entitie:

EF实体:

namespace Sistema.DataEntities.Models
{
public class Cliente
{
    public Cliente()
    {
    }

    public int ClienteID { get; set; }

    public string Nome { get; set; }
}

BLL:

布莱尔:

public class ClienteBLL : IClienteBLL
{
    readonly ISistemaContext _context;
    public ClienteBLL(ISistemaContext context)
    {
        _context = context;
    }

    public IEnumerable<Cliente> ClienteBLL_GetAll()
    {
        return _context.Cliente.AsEnumerable();
    }

    public Cliente ClienteBLL_GetByID(int id)
    {
        return _context.Cliente.Find(id);
    }

    public bool ClienteBLL_Adicionar(Cliente Obcliente)
    {
        _context.Cliente.Add(Obcliente);
        return _context.SaveChanges() > 0;
    }

    public bool ClienteBLL_Update(Cliente Obcliente)
    {
        _context.Cliente.Attach(Obcliente);
        _context.Entry(Obcliente).State = EntityState.Modified;
        return _context.SaveChanges() > 0;
    }

    public bool ClienteBLL_Delete(int id)
    {
        var clubMember = _context.Cliente.Find(id);
        _context.Cliente.Remove(clubMember);
        return _context.SaveChanges() > 0;
    }

采纳答案by Danilo Breda

UPDATE:

更新:

After 5 yearsthe internet is being the biggest focus on the company's projects, all new project are done through stateless APIs, and SPA frontend.

5 年后,互联网成为公司项目的最大焦点,所有新项目都是通过无状态 API 和 SPA 前端完成的。

回答by ken2k

I'm adding this as an answer (not a comment) even if it's not a final answer to your question (cause it's opinion-based) but it doesn't fit as a comment. That's just what I would do for a WPF application that requires a database.

我将其添加为答案(不是评论),即使它不是您问题的最终答案(因为它是基于意见的),但它不适合作为评论。对于需要数据库的 WPF 应用程序,这正是我要做的。

I would entirely drop the idea of directly connecting your WPF application to your database. I would build a 3-tiers architecture, i.e. I would create a stateless webservice that does all the stuff on server side.

我会完全放弃将 WPF 应用程序直接连接到数据库的想法。我会构建一个 3 层架构,即我会创建一个无状态的 web 服务,它在服务器端完成所有工作。

So you would have:

所以你会有:

  • the database
  • the webservice (using WCF), that is connected to the database, that does all the data stuff for you (I would even make it responsible of the businessstuff too)
  • the WPF application, that is connected to the webservice:
    • the View layer is your XAML + your code-behind
    • the ViewModel layer is, well, your ViewModels (out of scope of your question, but feel free to ask if you have any question about that layer). The ViewModels asynchronously call the webservice
    • the Model is the client WCF proxy
  • 数据库
  • 连接到数据库的 web 服务(使用 WCF),它为你处理所有数据(我什至会让它负责业务
  • 连接到 Web 服务的 WPF 应用程序:
    • 视图层是你的 XAML + 你的代码隐藏
    • ViewModel 层是您的 ViewModels(超出您的问题范围,但如果您对该层有任何疑问,请随时提问)。ViewModels 异步调用 webservice
    • 模型是客户端 WCF 代理

Some benefits of this approach:

这种方法的一些好处:

  • depending on the hardware/network harchitecture, could be a huge performance benefit to only make ONE call to the server instead of N calls(assuming the latency between the DB and the webservice (both on "server side") is lower than the one between the WPF application and the database)
  • more scalable
  • all benefits of the stateless approach: one Entity Framework context instantiation per webservice requests, so much easier to deal with concurrency issues (in case you have N WPF instances running concurrently)
  • easier to maintain (loose coupling between tiers)
  • easier to test (assuming you actually build tests)
  • better security (no need to expose a direct access to the database over the network)
  • 根据硬件/网络架构,仅对服务器进行一次调用而不是 N 次调用(假设 DB 和 Web 服务(均在“服务器端”)之间的延迟低于两者之间的延迟)可能会带来巨大的性能优势WPF 应用程序和数据库)
  • 更具可扩展性
  • 无状态方法的所有好处:每个 Web 服务请求一个实体框架上下文实例化,因此更容易处理并发问题(如果您有 N 个 WPF 实例同时运行)
  • 更容易维护(层之间的松散耦合)
  • 更容易测试(假设您实际构建测试)
  • 更好的安全性(无需通过网络公开对数据库的直接访问)