【发布时间】:2015-06-28 17:29:51
【问题描述】:
我在 C# 中使用了一个基于层概念的代码框架:
- 在底层,我们有数据层(数据库、远程服务等)。
- 正上方是访问层(与数据层交互的代码)。
- 正上方是持久层。 (用于在应用程序逻辑和数据层要求之间转换和转换数据的代码,以及处理方法调用的任何复合到复杂对象图和操作的访问。)
- 最后是流程层(带有通用应用程序逻辑的代码。)
每一层只与它上面或下面的层通信。所以一般的申请流程是
Processor -> Peristence -> Access -> Data
Data -> Access -> Persistence -> Processor
一般概念是,处理器充当包含 1 个或多个步骤的单个进程的一般表示。它由执行代码独立调用。但是一个过程很容易成为另一个更大过程的一个步骤。
我遇到的问题(或真正的潜在问题)是,当我有一个包含 1 个或多个子进程的进程,或者该进程使用持久性并且它有任何使用持久层的子进程时,我无法打开单个数据库连接供两个进程使用。每个进程都会实例化并打开自己的连接。例如,这里是一个实际的代码sn -p:
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 将实例化一个将连接到 Db 的 Peristence 层,而 PersentCurrentSurveyProcessor 还将实例化一个不同的持久性对象,该对象也将连接到同一个 Db。但是由于这种架构,它们不会共享连接并且无法以事务方式执行(如果需要)。
虽然我有一些想法,但我很想知道其他人可能会看到哪些我会忽略的解决方案。我不想最终打破我关于层只与它们的直接邻居交互的规则。
【问题讨论】:
-
创建一个 TransactionContext 对象,该对象可以选择性地传递到您的持久层调用中。该对象将包含使用现有连接所需的任何信息。如果传入,持久层将使用它,如果没有,持久层将创建一个并将其传回以供以后使用。为了在访问层中保留连接详细信息,这可以像访问层可以用来查找现有事务的令牌一样简单。添加一些记账代码,但让您的处理层不关心访问层。
-
您可以根据需要将它添加到需要它的持久性对象中。不需要进行“改变一切”更新。
-
嗯,首先,您必须了解创建两个连接并不是一件坏事,因为 .NET 使用连接池。事务问题可以通过加入 DTC 事务来解决,但这不会像本地事务那样执行。关键是,它可以支持具有多个连接的事务,但效率不会那么高。如果您关心的是效率,那么您将不得不为此制定一个横切关注点。
-
@Goblyn27 - 不,这是池的重点,它使连接保持打开状态。
-
@Goblyn27 提到 TransactionContext 是指 UnitOfWork 模式吗?
标签: c# architecture