C#建筑设计的不足
本文关键字:建筑设计 | 更新日期: 2023-09-27 18:00:16
我在C#中使用了一个基于层概念的代码框架:
- 在底层,我们有数据层(数据库、远程服务等)
- 正上方是访问层(用于与数据层交互的代码)
- 正上方是持久层。(用于在应用程序逻辑和数据层需求之间转换和转换数据的代码,以及处理方法调用到复杂对象图和操作访问中的任何组合。)
- 最后是流程层(使用通用应用程序逻辑的代码)
每个层只与它上面或下面的层通信。因此,一般的应用程序流程是
Processor -> Peristence -> Access -> Data
Data -> Access -> Persistence -> Processor
一般概念是,处理器充当包含1个或多个步骤的单个过程的一般表示。它由执行代码独立调用。但一个过程很容易成为另一个更大过程的一个步骤。
我遇到的问题(或真正的潜在问题)是,当我有一个包含1个或多个子进程的进程,或者该进程使用持久性,并且有任何子进程使用持久层时,我无法为两个进程打开一个DB连接。每个进程都会实例化并打开自己的连接。例如,这里有一个实际的代码片段:
var contactProcessor = new SelectContactProcessor();
var contact = contactProcessor.GetContact(contactId);
if (contact == null)
throw new Exception("Unable to locate contact");
viewModel.DisplayName = contact.DisplayName;
viewModel.City = contact.City;
viewModel.State = contact.State;
var processor = new PresentCurrentSurveyProcessor();
var data = processor.GetSurveyData();
if (data == null)
throw new Exception("Unable to locate survey");
viewModel.SurveyId = data.ID;
viewModel.SurveyName = data.SurveyName;
viewModel.StartDate = data.StartDate.ToShortDateString();
viewModel.EndDate = data.EndDate.ToShortDateString();
viewModel.Questions = data.Questions;
return viewModel;
因此,在本例中,SelectContactProcessor将实例化一个Peristence层,该层将连接到Db,而PersentCurrentSurveyProcessor也将实例化另一个持久性对象,该对象也将连接到同一Db。但由于这种架构,它们不会共享连接,也不能以事务方式执行(如果需要的话)。
虽然我有一些想法,但我很想知道其他人可能会看到我会忽视的解决这个问题的办法。我不想最终打破我关于层只与直接邻居交互的规则。
我将在这里对我的评论进行一点扩展。我的建议(以及@Goblin27显然的建议)是添加一个对象,该对象将包含一个开放连接的实例和您需要使用它的方法(例如启动/提交事务)。
在我开发的web应用程序中,我通常会将这样的对象放入DI容器中,因为每个请求只需要一个实例。然后,DI将它注入到任何需要它的服务中
这个对象还控制嵌套事务的使用(许多DB不支持这样做,所以我保留了一个startTransaction()
调用堆栈,由每个"commit()"弹出,实际上只有当这个堆栈为空时才提交。
您的应用程序有点不同,但您可以尝试使用相同的方式。
不过,我建议使用一些简单的DI容器,而不是四处传递全局变量。