2013-08-29 68 views
2

我一直在思考这个问题一段时间了,想不出一个可接受的解决方案。我有一个计划变得非常大的应用程序。正因为如此,我正在努力使其模块化。它基于MVC4。我还没有决定使用ORM或自己映射所有东西。我想有以下结构:实现LastUpdated和UpdatedBy的设计模式

---------------------- 
| Database 
---------------------- 
| Data/Data Access Layer (Class Library) (Objects reside here) 
---------------------- 
| Core MVC Project (User and Session are stored here) 
---------------------- 
| MVC Modules 

我想保持UpdatedBy场尽量靠近数据库尽可能的验证,可能在数据/数据访问层。问题是我想将user存储在Session中,并在类库中进行验证(没有Session)。我也想尽量避免在各地传递user。有没有办法将用户存储在Session中,并让数据访问层访问该信息而不通过user?任何人都有如何优雅地做这件事的建议?

编辑:我想保持validation,并CRUD活动尽量靠近数据层可能的,其中核心MVC项目只是调用对象和数据层上Save()验证对象,计算出修正哪些用户或创建它并将其保存到数据库。

编辑2:数据层必须在MVC层中完全没有依赖关系。

+2

可以创建依赖关系并将其注入到数据访问层,该数据访问层在创建会话时从会话中获取信息,但屏蔽了数据访问层不依赖于会话对象。 – Grax

+0

@Grax我会怎么做?我对依赖注入知之甚少。 – coryrwest

+0

现在你有什么技巧让你的图层分开? – Grax

回答

2

LastUpdated可以通过DB Insert/Updates上的Trigger轻松实现,但UpdatedBy有点棘手。

一个关键问题是“您的业务层是否需要知道谁在使用它?”如果是这样,那么可以将接口设计为在执行操作时要求提供用户名。如果不是,那么您需要使数据可以从业务层内部/后面访问,但不需要显式提供(例如使用依赖注入或通过提供始终可用的上下文)。

您可以考虑使用ActionFilters围绕您的控制器操作创建单独的审计跟踪,这可以轻松访问Session,并且可以创建用户所执行操作的运行历史记录。这可能会或可能不会正确地100%地记录到您的数据库记录中,但确实提供了应用程序操作的明确历史记录 - 这本身非常有价值。

您还可以考虑使用Command模式,从而应用程序生成在业务/数据层上制定的特定命令(例如,UpdateWidgetName命令)。在某些方面,这是MVC的工作原理,但具有明确的Command捕获用户和日期仍然是业务层的有用补充。


另外请注意记录本身的缺点。你只知道谁最后编辑了这个记录 - 你将无法具体分辨出他们编辑了什么,或者之前编辑过谁。对于相对简单的情况来说,这通常是足够的,但它远不能为记录提供实际的历史数据。

如果你真的想100%的审计,你应该看看Event Sourcing的设计模式,如果一个行动没有被审计,那么它没有发生。这是从典型的CRUD方法非常不同的模式,但非常强大的(虽然更复杂,最初设计)等


一个注意:考虑你的业务和持久代码为分隔条件两层。将它们捆绑在一起使业务逻辑与持久性(坏)紧密耦合,这将阻止它被重用。看看实施Repository这是致力于持久和检索您的业务对象。它回报。

+0

对不起,我是自学成才,正式名字上有点生疏。业务层是数据/数据访问层吗?我真正想要做的是保存谁更改了什么以及何时更改数据库的历史记录。我相信这就是你正在谈论的ActionFilter,我是否正确? – coryrwest

+0

http://en.wikipedia.org/wiki/Business_layer#Business_logic_layer < - 有一个很好的介绍。一个精心设计的业务层应该是可重用的,并且不应该有任何非业务依赖性(一个必须拥有SQL的业务层,或者只能被MVC使用,将被认为设计不佳)。为您的业务层创建一个专用项目,并尽量避免尽可能多地添加程序集引用 – STW

+0

我也是自学成才的。学习SOLID原则(以及如何应用它们)是一个巨大的里程碑,其他好的资源是模式书(PofEAA,头等第一设计模式等等),而令人大开眼界的是“Clean Code”。我已经向很多实习生推荐他们,他们通常都认为他们在获得导向 – STW

1

如果在应用程序中使用这样的结构,可以定义一些可在整个应用程序中使用的核心接口(如ICurrentUserProvider),然后可以在应用程序中最适合的部分实现这些接口而不会对应用程序的特定部分产生严密的耦合或依赖关系。

Project Structure

当你的web项目被初始化,它可以让你的控制器得到他们的依赖注入它们初始化DI框架。这样,您的控制器就可以获得所需的业务层服务,并且这些业务层服务具有他们所需的数据层实现(实际上并没有直接依赖于它们),数据访问对象获取可以告诉它的服务当前用户是(不直接依赖于MVC层)。