代码之家  ›  专栏  ›  技术社区  ›  Lahey

MVP:被动视图(带EF)和图层

  •  0
  • Lahey  · 技术社区  · 11 年前

    我正在使用MVP创建一个应用程序:被动视图和EF(模型优先)。据我所知,我有一个演示者直接从通过EF创建的DataContext中获取数据。它看起来像这样:

            private void UpdateOrderTableControl()
        {
            IList<Order> orders = dataContext.Orders.ToList();
            IList<OrderViewModel> viewOrders = new List<OrderViewModel>();
            foreach (var o in orders)
            {
                viewOrders.Add(new OrderViewModel()
                {
                    OrderId = o.Id,
                    CustomerId = o.CustomerId,
                    LastName = o.Address.LastName,
                    FirstName = o.Address.FirstName,
                    Company = o.Address.Company,
                    Weight = o.Weight,
                    Sum = o.Sum,
                    Date = o.Date
                });
            }
    
            view.GetOrderDataGridView().DataSource = viewOrders;
        }
    

    因此,演示者获取所有订单的列表,创建订单视图模型的列表(将来自不同表的数据组合在一起,即上面的地址),然后将视图模型列表发送到视图。

    相反,当从视图中检索数据以编辑或添加到数据库时,情况基本相同:

            private void SaveOrder()
        {
            GetOrderDataFromView();
    
            if (isNewOrder)
            {
                dataContext.Orders.Add(selectedOrder);
            }
            else
            {
                dataContext.Entry(selectedOrder).State = EntityState.Modified;
            }
    
            dataContext.SaveChanges();
            isSaved = true;
    
            UpdateOrderTableControl();
        }
    

    1) EF(通过EF创建的实体、DataContext等)是否可以被视为DAL?它应该在自己的项目中吗?

    2) 我想演示者不应该像那样访问DataContext,而是应该访问介于两者之间的另一层,对吧?那是服务层、业务层还是两者兼有?

    3) 我所说的视图模型实际上是视图模型还是其他东西?我只想把我的术语说对。

    编辑:

    4) 我读过一些关于向EF生成的实体添加业务逻辑的建议,但这听起来不太正确。我应该在EF之上的单独业务层中创建业务对象吗?这意味着我将拥有Order(由EF生成)、OrderBO(业务对象)和OrderViewModel(要显示的订单)。我必须做更多的映射,因为我会添加另一层,但这会使演示者更轻。

    提前谢谢!

    2 回复  |  直到 11 年前
        1
  •  1
  •   V-Lamp    11 年前

    好问题!

    好吧,所有这些问题的答案都取决于你计划做什么。你必须做的第一件事是评估实现每个模式所需的努力是否值得。

    1) 你是要在不同的表单实现之间切换,还是只对UI进行大规模的单元测试?那么,是的,被动的观点似乎是个好主意。

    2) 表单中有一个小代码不是很痛苦吗?然后 MVP supervising controller 可以更快地实现。

    3) 你的程序的大部分逻辑可以在业务层内部吗?在您拥有BL中的所有逻辑之后,GUI有多少特定的逻辑?如果没有那么多,那么在没有GUI模式的表单中编写代码是可行的。

    关于问题:

    1) 是的,EF可以被视为DAL,参与不同的项目也无妨。既然你喜欢模式,这里有一个有用的模式 Repository and Unit of Work Pattern 它抽象了EF,并允许您对BL进行单元测试。(使用伪造的DAL实现,在不访问实际数据库的情况下进行测试)

    2) 取决于。EF对象可以被视为数据传输对象,因为它们是POCO。DTO在所有层中都可见。另一种策略是拥有特定于层的对象,主要是在分层应用程序的场景中(不同机器中的每一层)。

    如果不强制执行其他操作,我将使EF对象对所有层都可见,但DataContext本身仅对BL可见,而对GUI层不可见。这意味着查询和事务是在BL中完成的,但GUI可以以相同的格式获得结果。

    3) 如果你遵循上面的建议,那么就不需要这种相当糟糕的对象复制了。

    4) 您所指的策略是 Domain Model (谷歌了解更多),在其中您将逻辑放入域对象中,域对象也可以访问数据库。同样,如果你听从了2)中的建议,这不会困扰你。

    在对模式及其正确的实现感到沮丧之前,请真正关注您的需求! 目标是快速交付和易于维护。过于抽象会伤害双方!

        2
  •  0
  •   Alexander Andronov    11 年前

    关于问题#2,最好在数据访问层上进行区分和抽象。如果您继续将其保存在Presenters中,这意味着您的客户端每次都会询问数据库,加载一些数据,然后进行一些计算。 如果您正在使用客户端服务器应用程序,最好不要混淆服务器逻辑和客户端逻辑。演示者肯定在客户端,DAL在服务器端。您可以使用web服务(例如asmx、wcf)将客户端连接到服务器。 我认为这样做至少有三个重要原因:

    1. 能够在没有真正后端和服务器逻辑的情况下在演示者上编写简单的单元测试
    2. 如果需要,可以扩展服务器端。
    3. 如果您在服务器端进行一些必要的计算,您将能够向客户端发送更少的数据

    关于#3,对于被动视图模式,有一个Presenter,它请求数据(有时称为模型),准备显示数据并发送到view进行渲染。在模型视图ViewModel模式中,ViewModel将向服务器发送请求并准备要显示的数据。MVVM和PassiveView之间的区别演示者和ViewModels如何使用View。在PassiveView中,演示者将了解View的接口,以便能够发送数据进行渲染。在MVVM中,View了解ViewModel并从ViewModel绑定数据。

    最后一个,#1。我认为是的,这是一些基础设施层。如果你在这里进行抽象,你将能够移动一些优化命令,设置加载选项(EF在这里非常灵活),并且你将能够快速完成。