我正在为我们的网站添加功能,它使用MSMQ异步执行长时间运行的进程.但是,执行此ansynch意味着我们需要在完成请求时通知用户.使用命令模式,我创建了一个名为INotify的接口*并将其组成到消息类中,因此消息处理类可以简单...
我正在为我们的网站添加功能,它使用MSMQ异步执行长时间运行的进程.但是,执行此ansynch意味着我们需要在完成请求时通知用户.使用命令模式,我创建了一个名为INotify的接口*并将其组成到消息类中,因此消息处理类可以简单地在消息的INotify对象上调用GiveNotice().第一个实现,EmailNotify,比预期更困难,因为我惊讶地发现MailMessage不可序列化,但它已经开始了.
现在我正在开发一个新的具体通知程序DBNotify,它将调用某种类型的SP并更新主事务数据库中的状态.我被绊倒了,因为我想重用我们已经创建的DAL架构,但是INotify是Model项目的成员,它比DAL更基础.
我们的层次结构如下所示:
常见>型号> DAL> BAL
这里有关于层级的更多细节.请记住,我从以下方面继承了:
Common负责应用程序中许多地方使用的所有“实用程序”功能,例如访问配置设置,解析字符串,非业务相关功能.
模型是业务对象,有些人称之为数据传输对象,是getter和setter的集合.我在这一层添加了一些“智能”,但只有该对象内部的业务规则,例如“一个项目的名称必须以字母数字字符开头”.
DAL是数据访问层,理论上,这里发生的所有事情都是模型对象被移入和移出数据库.
BAL是业务层;理论上,强制执行管理对象交互的业务规则(即“表单必须至少有两个项目”.).
因此,INotify接口被定义为抽象,以允许通知方法独立地变化(即电子邮件,TXT,推特等).它是系统的基础,因此我在Model层创建了它,它独立于DAL层.但是,我正在创建一个新的INotify具体实现,其通知方法是在数据库中调用SP.
有没有其他人处理过一个业务对象,其目的是与数据库进行交互,以及如何将其置于您的N层架构中?
在你告诉我使用Linq to Sql之前,非常感谢.这不是一个技术问题(我该怎么做),这是一个设计问题(我该怎么做).
我认为StackExchange站点更侧重于这些与语言无关的设计问题,因此我将在那里复制它.
最佳答案:
也许不是你问题的真正答案,但是要考虑一些事情.
我对您在组件层次结构中放置数据访问权限感到困惑.我不会把它放在两个功能域层之间.甚至不在单个域模型类“之上”.数据访问或持久性不是任何域类的关注点.它应该只是可以对他们做的事情,而不是他们做的事情.
即使我开始编写像TClient.Save和TClient.Load之类的东西,我现在得出的结论是,不是客户决定需要保存,而是用户交互决定何时需要域实例的数据,因此应该加载,并且当客户的数据应该被保留时,如果有的话.因此,我现在支持编码(在GUI中,更具体地说是GUI中的控制器),如DataStore.Load(ClientInstance)和DataStore.Save(ClientInstance).然后由数据访问层决定如何执行此操作.它可以在C#中使用反射,或者在Delphi中使用新的RTTI来迭代所有客户端的属性,以便它们可以将它们发送到数据库.
虽然分层是一个非常好的概念,可以通过简单地坚持“你可以调用而不是向上”来分离问题,并防止你把东西放在一起,但在解决诸如日志记录,异常处理,通知之类的问题时,它并没有多大帮助.以及其他所有组件/层需要的其他有趣的横切关注点.
此外,Common层,因为它是一个实用程序层,所以其他所有层都应该可以访问它.
把它全部放在一张图片中(我在你的简单域类,模型和跨类业务规则,你的BAL之间保持区别):
+---+ +-------------+
| C |<--| Data Access |<--------------------------+
| o | +-------------+ |
| m | | |
| m | | |
| o | v |
| n | +-------------+ +----------------+ +-----+
| |<--| Model +<--| Cross class |<--| GUI |
| | +-------------+ | business rules | | |
| | | | | |
| |<--------------------| | | |
| | +----------------+ | |
| | | |
| |<-----------------------------------------| |
+---+ +-----+
调用数据库的INotify实现当前在模型中,在上图中,它不会调用数据访问层本身,它只被数据访问层调用或者更确切地询问.
问题实际上是INotify是否应该在“模型”中,是域层的一部分,或者它是否应该是一个公共接口,并且应该有一个可以从域和GUI访问的单独的“通知”层/组件.这个新组件不仅可以关注通知,还可以关注许多其他交叉问题,例如日志记录.它至少以某种回调方式访问公共(当然)和数据访问组件以及GUI.
在下图中,我试图想象这一点,但我不太擅长可视化,并且总是遇到那些讨厌的十字刀.这就是为什么没有从域层到交叉问题的调用箭头,尽管领域层当然应该能够访问例如“Logger”接口.也许我正在努力区分常见组件和交叉组件,并且可以将这些组合在一起,并将它们视为“实用程序”层/组件中的单独块.
+--------------------------------------------+
+-----| Cross cutting concerns |
| +--------------------------------------------+
v v^ ^
+---+ +-------------+ |
| C |<--| Data Access |<--------------------------+ |
| o | +-------------+ | |
| m | | | |
| m | | | |
| o | v | v
| n | +-------------+ +----------------+ +-----+
| |<--| Model +<--| Cross class |<--| GUI |
| | +-------------+ | business rules | | |
| | | | | |
| |<--------------------| | | |
| | +----------------+ | |
| | | |
| |<-----------------------------------------| |
+---+ +-----+
本文标题为:c# – 在N层体系结构中实现数据库功能对象?
基础教程推荐
- C# 使用GDI绘制雷达图的实例 2023-02-03
- c# 使用模式匹配以及 is 和 as 运算符安全地进行强制转换 2023-03-14
- C#中使用Spire.XLS来操作Excel数据的实现 2023-07-18
- 10分钟学会VS NuGet包私有化部署 2023-05-05
- Unity游戏开发实现背包系统的示例详解 2023-06-28
- c#中winform根据邮箱地址和密码一键发送email的实现 2023-06-21
- C#结合AForge实现摄像头录像 2022-11-15
- LINQ操作符SelectMany的用法 2023-05-23
- Unity多屏幕设置的具体方案 2023-06-05
- C# 中 “$” 符号的作用以及用法详解 2023-02-25