4

假设我有 3 层

第 1 层:WPF 项目(包含:xaml、viewmodels、mvvm 框架)

第 2 层:业务逻辑层(包含:普通 c# 类)

第 3 层:实体框架(包含:存储库/数据访问类)

当您不想将 DAL(第 3 层)暴露给视图(第 1 层)时,您如何很好地实现业务逻辑层?我很难在 BLL 对象和 DAL 实体之间来回设置值。

你能帮忙吗?

4

7 回答 7

4

实体框架在“断开连接”的模型中不能很好地工作。除非有什么改变,否则我永远无法让它轻松地工作。

您可以在第 2 层中使用 AutoMapper 创建 ViewModel 以呈现给第 1 层,但是您仍然必须将更改发送回第 3 层,这可能会很痛苦。

于 2012-08-22T16:40:52.250 回答
3

如果你只是在开发一个在可预见的情况下不会改变的小应用程序,那么现在就做最快的事情。如果您想要一个长期可维护的应用程序,那么让我提出以下内容。

这种垂直层方法的问题在于,当您需要视图中的某些内容时,您必须将其添加到业务层(即使业务层不关心它)和数据层。这要求您的业务层看起来像 1) 数据的 UI 视图 2) 数据的业务视图和 3) 数据的数据库表示。那和/或您需要在层之间进行大量映射。所有这些都淡化了业务层表示业务逻辑的实际目的。然后往往会发生的是,所有业务逻辑都被迁移到事务方法(也可以是静态方法)中,以仅更改数据对象的状态。如果您的问题域只是没有复杂逻辑的 CRUD,那完全没有错。复杂的逻辑,

假设您有复杂的逻辑,数据的用户视图和数据的业务表示通常是非常不同的,因此 UI 视图最终会得到专门的数据模型。如果我是你,我会接受这一点并使用 CQRS 原则的简单版本。也就是说,让您的 UI 视图的数据来自与执行业务操作的地方不同的地方。在您的情况下,我可能在您的 DAL 中有一个 EF 模型,它只为您的 UI 视图提供服务,并准确地为它们提供所需的东西(无论是通过数据库视图、存储过程还是预编译的报告表)。然后创建一个单独的 EF 模型,该模型仅服务于您的业务实体的需求。然后,当您准备好执行实际业务操作时,UI 的 viewmodel 操作方法可以从业务 EF 模型加载业务对象(或者更好的是,从执行此操作的业务层调用对象工厂)并对业务对象运行适当的操作。请注意,我在这里还假设您的数据库是高度相关的(主要是第 2 和第 3 范式),并且您已准备好使用 EF。

我不会尝试将您的视图模型变成业务逻辑。这使得您的业务逻辑不容易在其他平台或应用程序(如 Web)上重用。MVVM 应该只服务于 UI。在我看来,V(视图)代表用户看到和操作的内容。M(模型)代表用户在该视图上选择的内容。VM(视图模型)在两者之间进行转换。然后,您的程序应采用用户的验证选择(UI 模型)并从中提取所需的数据以执行适当的业务操作。

于 2012-08-22T17:42:59.937 回答
2

无需将所有 DAL 暴露给视图层,只需在所有层之间交换域对象(EF 对象)。该结构可能类似于以下内容:

  1. 表示层-------- ^
  2. BLL --------------------------- | 数据对象
  3. DAL(存储库等)--- |

因此,您的所有层都将断开连接;但它们将共享相同的域对象。在现实世界中,您可以通过为所有层共享的实体框架实体创建单独的 dll 来实现类似的结构。请注意,ObjectContext 仅对 DAL 可见(默认情况下,实体和对象上下文在同一个 dll 中生成,您需要将其分成两个 dll)。

于 2012-08-22T16:44:49.737 回答
1

ViewModels MVVM 中的应用程序,因此它们应该通过您的存储库类或业务逻辑(直接或间接使用您的验证类)处理诸如数据访问之类的事情。

如果您不想直接引用这些类,请使用 anInterface但请注意,您需要通过某种方式将继承的类传递给 ViewModel。我曾经做过一个项目,我们有一个共享接口库,这样的IRepository接口,所有的东西都是使用 MEF 导入/导出的,所以这些层没有直接相互引用。

最终(简化的)布局是:

  • 模型-> 包含可以对自己的数据(长度、最小/最大值等)进行简单验证但不进行任何高级验证或业务逻辑的纯数据对象。没有引用任何其他库。

  • Common -> 包含的接口、实用程序和其他常用共享类。仅引用模型库。

  • DAL -> 基于公共库中的存储库接口的包含数据访问和存储库。接口定义和实用程序的引用公共库,以及模型库,因为它包含在数据访问调用中使用或返回的数据模型

  • ViewModels -> 包含的应用程序和业务逻辑。引用 Common 的实用程序和接口,以及 Models 的数据模型

  • 客户端-> 包含的视图。引用模型和视图模型,因此它可以DataTemplates为两种对象类型编写

于 2012-08-22T16:46:27.233 回答
1

除了 Daryal 的回答之外,您还可以将 BL 中的业务对象定义为 POCO,并在 DAL 层中使用 EF 从数据库中读取它们或将它们保存到数据库中。

如果您在 BL(或工作单元,无论您给它什么命名)中定义一个类似存储库的接口,并在您的 DAL 中实现该接口,那么您只需要一点 DI 即可获取存储库的实例 -类,而不必一直引用 DAL。它对我来说就像一个魅力。

有关更多信息,请参见此处此处

于 2012-08-22T16:50:43.470 回答
0

实体框架本身应该用作“逻辑层”。

你的想法可能有一定的意义,使用组合技术。

然而,我认为其中一些微型。设计为单独使用的库,除非在其网站中明确合并和提及。

祝你好运。

于 2012-08-22T16:43:31.280 回答
0

我是第二个,我已经在一些项目中实现了这一点。使用 POCO 作为业务对象是绝对可以的。

另一种方法不是创建 2 个项目(一个用于 DB 上下文,一个用于实体)是仅使用一个 DAL/DATA 项目并在 BLL 中引用它。然后继承 BLL 中的 POCO 类,并在 UI 层使用该类。以下是基本示例代码:

// assume this is EF generated POCO
namespace Owner.Project.Data{
    public partial class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
    }
}

// this is manually created class in BLL
using Owner.Project.Data;
namespace Owner.Product.Business{
    public class StoreProduct : Product {
        public bool Add (string productName){
            // TODO - add product using EF as you normally do
        }
    }
}

现在您可以在您的 UI 项目中引用 BLL 并在那里使用 StoreProduct 类。要实现松耦合模式,当然您也可以从 IStoreProduct 接口继承 StoreProduct 类,并在 UI 或 Web 服务中使用它,但这是另一个话题。

于 2017-04-15T13:08:59.153 回答