ASP.NET MVC3 - 3 Tier design - 事务控制和业务层设计问题

发布于 2024-12-10 03:17:02 字数 1053 浏览 0 评论 0原文

我正在设计一个 ASP.NET MVC3 应用程序,我希望在 3 层架构中清晰地分离关注点。我使用 Fluent NHibernate 作为 ORM,即使用 NHibernate 映射的实体的存储库模式。我想添加一个具有工作单元模式的适当业务层,保留 MVC 部分仅用于表示(通过使用通过业务层映射到 nHibernate 实体的 ViewModel)。 本文介绍了组合的 3 层和 MVC 架构很好。

根据此 MVC + 工作单元 + 存储库 文章 我没有看到业务层的明显区别。工作单元类为每个存储库类型提供强类型的 getter,这看起来适合业务层。然而,它公开了一个 Save 方法,我认为该方法将转换为 nHibernate 的 BeginTransaction 和 CommitTransaction 方法。这引出了一些问题:

1)将事务控制暴露给 MVC 是一个好主意吗?事务控制应该在哪个阶段发生?在我看来,MVC 不应该负责事务,但是如何避免呢?

2)是否应该有某种自动方式来处理交易? 这个 ActionFilter 实现是半自动的,但事务控制显然是在MVC部分,不是业务层。

3)UnitOfWork类与业务层类相同吗?
- 如果是这样,是否意味着我们可以向其中添加自定义业务逻辑方法?
- 如果没有,我们是否将工作单元与包含业务逻辑方法的其他类包装在一起?

我很欣赏任何想法或例子。谢谢。

I am designing an ASP.NET MVC3 application, and I would like to have a clear separation of concerns in a 3 layer architecture. I am using Fluent NHibernate as the ORM, the Repository pattern to work with the entities mapped by NHibernate. I would like to add a proper business layer with a Unit Of Work pattern, keeping the MVC portion only for presentation (by using ViewModels that map to the nHibernate entities through the business layer). This article describes the combined 3-tier and MVC architectures nicely.

According to this MVC + unit of work + repository article I don't see a clear distinction of a business layer. The unit of work class presents strongly typed getters for each repository type, which looks appropriate for a business layer. However, it exposes a Save method, which I think would translate to BeginTransaction and CommitTransaction methods with nHibernate. This begs some questions:

1) Is exposing transaction control to MVC a good idea? At which stage should transaction control happen? Seems to me that MVC should not be responsible for transactions, but how to avoid that?

2) Should there be some automatic way to handle transactions? This ActionFilter implementation is semi-automatic but the transaction control is clearly in the MVC section, which is not the business layer.

3) Is the UnitOfWork class the same as a business layer class?
- if so, does that mean that we can add custom business logic methods into it?
- if not, do we wrap the unit of work with some other class(es) that contains business logic methods?

I appreciate any ideas or examples. Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一桥轻雨一伞开 2024-12-17 03:17:02

首先,我想澄清关于业务层的一点误解,因为您想使用存储库模式,并且您的设置是 领域驱动设计,那么业务层实际上就是【领域模型(实体和值对象,您可以在其中设计业务逻辑实体和对象中的面向对象方式),应用层协调事务和操作以及域层的命令],因此建议的架构将是这样的:

  • 表示(MVC)[OrderView,OrderPresentationModel, OrderController]
  • 应用程序 [OrderService]
    • 使用 UnitOfWork(事务)和存储库来执行域逻辑
    • DTO [OrderDTO、CustomerDTO]
    • 实体和值对象 [订单、客户、LineItem、地址]
    • 存储库接口 [IOrderRepository、ICustomerRepository]
    • (可选)工作单元接口 [IUnitOfWork]
  • Infrastructure.DataAccess(使用 ORM 或数据访问技术)
    • 存储库 [OrderRepository、CustomerRepository]
    • (可选)工作单元 [UnitOfWork]
  • Infrastructure.Common
    • 记录
    • 实用程序

示例场景:

[演示] OrderController:

 _orderService.CreateOrder(OrderDTO);

[应用程序] OrderService:

 _unitOfWork.BeginTransaction();
 var customer = _customerRepository.GetById(orderDTO.CustomerId);
 var order = new Order() { Customer=customer, Price=orderDTO.Price, ... }
 _orderRepository.Add(order);
 _unitOfWork.Commit();

关于您的问题:

1) 将事务控制暴露给 MVC 是一个好主意吗?事务控制应该在哪个阶段发生?在我看来,MVC 不应该负责事务,但是如何避免呢?

不,我更愿意将其分离在应用程序层中,以便使设计灵活以支持不同的演示。

2)是否应该有某种自动方式来处理交易?这个ActionFilter实现是半自动的,但是事务控制显然是在MVC部分,而不是业务层。

在应用层使用事务。

3)UnitOfWork类与业务层类相同吗?
- 如果是这样,这是否意味着我们可以向其中添加自定义业务逻辑方法?
- 如果没有,我们是否将工作单元与包含业务逻辑方法的其他类包装在一起?

不,这只是将任务分组为事务的一种方法。
业务逻辑实际上封装在实体中,如果逻辑与一个实体无关,则应在域服务 [TransferService.Transfer(account1, account2, amount)] 中实现,用于协调、访问存储库和应用程序事务层就是这个地方。

First of all I want to clarify a little mis-conception about the business layer, as you want to use the Repository pattern and your setup is a candidate to Domain Driven Design, then the business layer is actually [the Domain Model (Entities and Value Objects where you design your business logic in an object oriented fashion in entities and objects) , and Application Layer to co-ordinate transactions and operations and commands to the domain layer], so the suggested architecture would be something like this:

  • Presentation (MVC) [OrderView, OrderPresentationModel, OrderController]
  • Application [OrderService]
    • Use UnitOfWork (Transactions) and Repositories to execute domain logic
    • DTOs [OrderDTO, CustomerDTO]
  • Domain
    • Entities and Value Objects [Order, Customer, LineItem, Address]
    • Repository Interfaces [IOrderRepository, ICustomerRepository]
    • (optional) Unit of Work Interface [IUnitOfWork]
  • Infrastructure.DataAccess (Using ORM or Data Access Technology)
    • Repositories [OrderRepository, CustomerRepository]
    • (optional) Unit of Work [UnitOfWork]
  • Infrastructure.Common
    • Logging
    • Utilities

Example scenario:

[Presentation] OrderController:

 _orderService.CreateOrder(OrderDTO);

[Application] OrderService:

 _unitOfWork.BeginTransaction();
 var customer = _customerRepository.GetById(orderDTO.CustomerId);
 var order = new Order() { Customer=customer, Price=orderDTO.Price, ... }
 _orderRepository.Add(order);
 _unitOfWork.Commit();

About your questions:

1) Is exposing transaction control to MVC a good idea? At which stage should transaction control happen? Seems to me that MVC should not be responsible for transactions, but how to avoid that?

No, i would prefer to separate it in application layer in order to make design flexible to support different presentations.

2) Should there be some automatic way to handle transactions? This ActionFilter implementation is semi-automatic but the transaction control is clearly in the MVC section, which is not the business layer.

Use transactions in application layer.

3) Is the UnitOfWork class the same as a business layer class?
- if so, does that mean that we can add custom business logic methods into it?
- if not, do we wrap the unit of work with some other class(es) that contains business logic methods?

No, it is just a way to group tasks into transactions.
The business logic actually is encapsulated in entities and if the logic is not related to one entity it should be implemented in domain services [TransferService.Transfer(account1, account2, amount)], for co-ordinations, accessing repositories, and transactions the application layer is the place.

聽兲甴掵 2024-12-17 03:17:02

您是否研究过 S#arp 架构?它具有内置的 MVC 事务处理,使用操作过滤器。

我通常是一个分层纯粹主义者,所以我并不热衷于让 MVC 打开视图,但我已经开始喜欢它了。

各有利弊,但以下是在视图中打开会话模式的一些优点。

  1. 延迟加载——如果您可以在 MVC 视图中依赖延迟加载,它将简化您的数据访问。无需显式联接到视图所需的所有表。 (请务必在延迟加载时通过显式加入来避免 N+1 问题会产生大量的查询。数据网格是这里的常见罪魁祸首。)
  2. 更简单的 BSO 层——您的 BSO 不需要担心会话。假设您已经在会话上下文中工作。

如果您不想使用 S#arp,您仍然可以自己实现 Open-Session-In-View,只需在 ActionFilter 中添加几行代码。在操作执行方法上,打开会话。在操作执行方法中,提交、关闭和处置。这就是我们在我的项目中所做的事情,它对我们来说效果很好。

Have you looked into the S#arp Architecture? It has built-in MVC Transaction handling, using Action Filters.

I'm usually a layering purist, so I wasn't psyched about letting MVC open the view, but I've come to like it.

There are pro's and con's, but here are some advantages of the Open Session In View pattern.:

  1. Lazy Loading -- It will simplify your data access if you can rely on lazy loading in your MVC Views. No need to explicitly join to all tables required by the view. (Be sure to avoid the N+1 problem by joining explicitly when lazy loading would generate a ridiculous number of queries. Data grids are a common culprit here.)
  2. Simpler BSO layer -- your BSO doesn't need to worry about sessions. It's assumed that you're already working in the context of a session.

If you don't want to go with S#arp, you can still implement Open-Session-In-View yourself with only a few lines of code in an ActionFilter. On the Action Executing method, open the session. In the action executed method, commit, close, and dispose. This is what we're doing on my project and it has worked well for us.

十二 2024-12-17 03:17:02

任何基于 Web 的应用程序都会遇到的问题是,由于需要通过 HTTP 会话管理对象生命周期,因此 UI 与业务层之间必须存在某种耦合。在典型的桌面应用程序中,您不必担心会话,因此这使得可以轻松地将所有事务处理移至链的下游。

考虑一下您希望在三个应用程序(网站、Web 服务和桌面应用程序)中重用相同逻辑的位置。如果不将事务处理暴露给表示层,就没有处理事务提交的好方法,因为业务层不知道对象将存在多长时间。

因此,您的选择是,要么确保提交业务对象的每个方法中的所有内容,要么将事务公开给 UI。

第三种选择是构建一个相当复杂的会话管理控制器,我什至不想考虑......会话管理控制器可以耦合到用户界面和业务逻辑,在某种程度上将它们分开......但是这需要更多的分析。

The problem you have with any web based app is that there has to be some coupling of the UI to the buisness layer due to the need to manage object lifetimes by the HTTP Session. In a typical desktop application you don't have to worry about sessions, so this makes it easy to move all transaction handling further down the chain.

Consider where you want to reuse the same logic in three apps, a Web Site, a Web Service, and a Desktop application. Without exposing the transaction handling to the presentation tier, there's no good way to deal with transaction commits, beacuse the business layer is ignorant of how long the objects will exist.

So your choice is, either make sure you commit everything in every method of your buisness objects, or expose the transaction to the UI.

A third alternative would be to build a fairly complex session management controller, which I don't even want to think about... The session management controller could be coupled to the ui and the business logic, seperating them to some extent.. But that would require a lot more analysis.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文