我一直在思考这个问题一段时间,并且想不出一个可以接受的解决方案。我有一个计划变得非常大的应用程序。因此,我试图使其模块化。它基于MVC4。我还没有决定使用ORM或自己映射一切。我想有以下结构:
----------------------
| 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层中完全没有依赖关系。
答案 0 :(得分:2)
LastUpdated
可以通过数据库插入/更新Trigger
轻松实现,但UpdatedBy
有点棘手。
一个关键问题是“您的业务层是否需要了解谁在使用它?”如果是这样,那么接口可以设计为在进行操作时要求提供用户名。如果没有,那么您需要从业务层内部/后面访问数据,但不要明确地提供给它(例如使用依赖注入,或者通过提供可用的Context)。
您可以考虑使用围绕控制器操作的ActionFilters创建单独的审计跟踪,从而可以轻松访问Session
,并可以创建用户执行操作的运行历史记录。这可能会或可能不会正确地100%到您的数据库记录,但确实提供了应用程序操作的清晰历史记录 - 这本身就很有价值。
您还可以考虑使用Command
模式,从而应用程序生成在业务/数据层上制定的特定命令(例如UpdateWidgetName
命令)。在某些方面,这就是MVC已经运行的方式,但拥有一个明确的Command
来捕获用户和日期仍然是您业务层的有用补充。
还要注意将此保留在记录本身上的缺点。您只会知道上次编辑记录的人员 - 您将无法具体说明他们编辑的内容或之前编辑过的内容。对于相对简单的场景,这通常就足够了,但它远远没有为记录提供实际的历史数据。
如果您真的想要100%审核,那么您应该查看Event Sourcing
设计模式,如果某个操作未经过审核,那么有效的情况就不会发生。这是典型的CRUD方法的一种非常不同的范例,但功能非常强大(虽然最初设计起来比较复杂)
另一个注意事项:考虑将业务和持久性代码分为两层。将它们绑在一起使得业务逻辑与持久性(坏)紧密耦合,这将阻止它被重用。考虑实现专用于持久化和检索业务对象的Repository
。它得到了回报。
答案 1 :(得分:1)
如果在应用程序中使用这样的结构,则可以定义一些可在整个应用程序中使用的核心接口(如ICurrentUserProvider
),然后您可以在应用程序的部分中实现这些接口它们是最好的实现,而不会与应用程序的特定部分建立紧密耦合或依赖。
当您的Web项目初始化时,它可以初始化您的DI框架,以便您的控制器将其依赖项注入其中。这样,您的控制器就可以获得所需的业务层服务,并且这些业务层服务具有所需的数据层实现(实际上并没有直接依赖它们),而数据访问对象获取的服务可以告诉它谁当前用户是(不直接依赖于MVC层)。