将业务层与数据层分离时对实体进行限制的位置

2024-04-25

我正在尝试为我的大型 ASP.NET MVC 应用程序创建业务层和数据层。因为这是我第一次尝试这种规模的项目,所以我正在阅读一些书籍,并努力小心地将事物正确地分开。通常,我的应用程序混合了业务逻辑和数据访问层,并且多个业务实体在单个类中交织在一起(当我试图弄清楚在哪里添加内容时,这让我很困惑)。

我读过的大部分内容都是将业务层和数据层分开。这看起来一切都很好,但我很难想象在某些情况下如何做到这一点。例如,假设我正在创建一个允许管理员向系统添加新产品的系统:

public class Product
{ 
   public int Id { get; private set; }
   public string Name { get; set; }
   public decimal Price { get; set; }
}

然后我通过创建存储库来分离数据访问

public class ProductRepository
{
   public bool Add(Product product);
}

假设我想要要求产品名称至少包含 4 个字符。我不知道如何干净地做到这一点。

我的一个想法是扩展 Name 的 set 属性,并且仅在长度为 4 个字符时才设置它。但是,创建产品的方法无法知道名称未设置,除非 Product.Name != 他们传入的任何内容。

我的另一个想法是将它放在存储库中的 Add() 方法中,但随后我的业务逻辑和数据逻辑就在那里,这也意味着如果 Add 调用失败,我不知道它是否失败了业务逻辑或因为 DAL 失败(这也意味着我无法使用模拟框架测试它)。

我唯一能想到的就是将我的 DAL 内容放在第三层中,该第三层从存储库中的 Add() 方法调用,但我在我的书或网站上的任何域建模示例中都没有看到这一点。网络(至少我见过)。当我不确定是否需要时,它还会增加域模型的复杂性。

另一个示例是希望确保名称仅由一个产品使用。它会放在 Product 类、ProductRepository Add() 方法中还是哪里?

附带说明一下,我计划使用 NHibernate 作为我的 ORM,但是,要实现我想要的目标(理论上),我使用什么 ORM 并不重要,因为 TDD 应该能够隔离所有这些。

提前致谢!


我通常通过使用分层架构来解决这个问题。这个怎么做?您基本上有以下(理想情况下)VS 项目:

  • 表示层(UI 内容所在的位置)
  • 业务层(实际业务逻辑所在)
  • 数据访问层(与底层 DBMS 通信的地方)

为了解耦所有这些,我使用所谓的接口层。最后我有

  • 表示层(UI 东西驻留)
  • IBusiness 层(包含 业务层)
  • 业务层(其中 实际的业务逻辑所在)
  • IDataAccess层(包含 DAO层的接口)
  • 数据访问层(您进行通信的地方) 与您的底层 DBMS)

这非常方便,并且创建了一个很好的解耦架构。基本上,您的表示层仅访问接口,而不访问实现本身。为了创建相应的实例,您应该使用工厂或最好使用一些依赖注入库(Unity http://www.codeplex.com/unity适用于 .Net 应用程序或 Spring.Net)。

这对您的应用程序的业务逻辑/可测试性有何影响?
详细编写所有内容可能太长,但如果您担心拥有良好的可测试设计,则绝对应该考虑依赖项注入库。

使用 NHibernate,...无论什么 ORM
通过接口将 DAO 层与其他层完全分离,您可以使用背后的任何技术来访问底层数据库。您可以根据需要直接发出 SQL 查询或使用 NHibernate。好处是它完全独立于应用程序的其余部分。您可以从今天开始手动编写 SQL,明天将您的 DAO dll 与使用 NHibernate 的 dll 交换,而无需对 BL 或表示层进行任何更改。
而且测试你的 BL 逻辑很简单。你可能有这样的课程:

public class ProductsBl : IProductsBL
{

   //this gets injected by some framework
   public IProductsDao ProductsDao { get; set; }

   public void SaveProduct(Product product)
   {
      //do validation against the product object and react appropriately
      ...

      //persist it down if valid
      ProductsDao.PersistProduct(product);
   }

   ...
}

现在您可以轻松地测试您的验证逻辑SaveProduct(...)方法通过模拟测试用例中的 ProductDao 来实现。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将业务层与数据层分离时对实体进行限制的位置 的相关文章

  • 使用 monad 堆栈进行依赖注入

    I m 尝试不同的方法执行有时称为依赖项注入的操作 为此 我详细阐述了一个天气应用程序的简单示例 我们要在其中获取天气数据 从网络服务或硬件设备 存储天气数据 可以是数据库或简单的文件 并报告 将其打印到屏幕上 或说出天气 这个想法是编写一
  • 业务验证逻辑代码异味

    考虑以下代码 partial class OurBusinessObject partial void OnOurPropertyChanged if ValidateOurProperty this OurProperty false t
  • 在 .Net 中,如何使用 OleDB 以我想要的格式从 CSV 导入值?

    我有一个 CSV 文件 其中有一列包含看起来像整数的字符串 也就是说 它们应该作为字符串处理 但由于它们是数字 因此它们似乎作为整数导入 去掉前导零 示例数据 0000000000079 0000999000012 000100200000
  • 什么模式最适合开发规则/决策引擎[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 Hibernate 中限制数据库级别的用户访问

    The App 我需要实现一个可供不同用户使用的网络应用程序 每个用户对不同的表有不同的权限 例如 用户 A 可以看到表中的 名称 和 地址 字段Student 用户 B 可以看到表中的 姓名 和 电话号码 字段 但看不到 地址 Stude
  • 如果我必须为 Oracle .net Entity Framework 定义 app.config 中的每个字段,那么 ORM 的意义何在?

    据我所知 实体框架的重点是简化和统一数据访问模型 我下载了最新的 Oracle net 工具 ODAC 11 2 第 4 版 该工具声称支持 EF4 并且我正在尝试导入一些 Oracle 存储过程 通过函数导入 该过程将一个引用游标作为输出
  • 如何从 C# 类生成数据库表?

    有谁知道为给定类自动生成数据库表的方法 我并不是在寻找整个持久层 我已经有了一个正在使用的数据访问解决方案 但我突然必须存储来自大量类的大量信息 而且我真的不想创建所有这些桌子都是手工制作的 例如 给定以下类 class Foo priva
  • Rails 中的业务逻辑在哪里?

    我是一名 ASP NET MVC 开发人员 刚刚开始我的第一个 Rails 大型项目 但是我很困惑将业务逻辑放在哪里 在 ASP NET 上 我创建了一个包含处理业务逻辑的服务 域驱动设计 的库 我听说 Rails 使用胖模型瘦控制器的概念
  • 如何告诉 Ninject 绑定到它没有引用的实现

    我在用着NinjectMVC3 http nuget org List Packages Ninject MVC3在我的 ASP NET MVC3 项目中 我有3层 Foo Web Foo 服务 Foo Data Foo Web 引用 Fo
  • 使用 ASP.NET MVC 3 本地化非数据注释错误的最佳方法是什么?

    借助数据注释 现在可以轻松使用 Resource resx 文件本地化错误消息 例如 public class Student Required ErrorMessageResourceName Required ErrorMessageR
  • 使用接口编写 DAO 类

    我正在创建一个新的 Web 应用程序 它将使用一堆数据访问对象 DAO 类对数据进行 CRUD 操作 我知道当我有外部用户 应用程序使用我的 DAO 类时我应该编写 java 接口 但如果没有这样的需要 你认为我还应该写接口吗 我将使用 s
  • 现在N层架构意味着什么?

    从传统意义上讲 N 层意味着将应用程序分成 层 并将每个 层 放在不同的服务器上 这样做至少有 3 个原因 维护 a 代码维护 更容易进行错误修复和功能添加 b 硬件维护 关闭一台服务器不会中断其他层的服务 性能 一台服务器的速度通常不够快
  • 我应该使用公共变量还是私有变量?

    我第一次做一个大型项目 我有很多类 其中一些具有公共变量 一些具有带有 setter 和 getter 方法的私有变量 并且相同具有两种类型 我决定重写此代码以主要仅使用一种类型 但我不知道应该使用哪个 仅用于同一对象中的方法的变量始终是私
  • 将 MySQL 连接到 Visual Studio C#

    我正在尝试编写数据访问代码以将 MySQL 连接到 Visual Studio 到目前为止我有这段代码 但我不知道它是否正确 我正在使用我的书 并注释掉了一些其他内容 但是当我包含注释掉的信息时 我收到了错误 public static M
  • 用户输入是否进入控制器或模型?

    现在我已经拆分了模型 但我的控制器和视图仍然组合在一个 12k 行文件中 我一直在寻求为此创建一个真正的 MVC 系统 拆分视图 但是在寻找要拆分的内容时 我注意到我的控制器正在执行大量可能属于模型的工作 例如 假设我有 if isset
  • 我想我需要一个简单的规则引擎? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 将 Tkinter UI 关注点与 Python 应用程序中的逻辑分离

    这是我的第一个应用程序 它运行良好 但我想将 UI 问题 例如获取输入和创建标签 与翻译逻辑分开 然后 我想删除先前翻译的输出 即一次仅在屏幕上显示一个翻译 如何将翻译逻辑与 Tkinter GUI 分开 from Tkinter impo
  • Java EE 5 和 Hibernate

    我可以将哪个版本的 Hibernate 与 Java EE 5 一起使用 我可以使用最新版本吗 See http www hibernate org http www hibernate org 它说最新的4 1 4版本可以与Java EE
  • 业务逻辑是主观的吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为实体框架中的实体创建基类

    我想创建一个对我的所有实体都通用的基类 该类将具有 Save Delete GetByID 等方法以及其他一些基本功能和属性 我在 Linq to SQL 方面有更多经验 希望能在 EF 中获得一些类似的好示例 谢谢 像这样 public

随机推荐