我对此非常陌生,我正在努力寻找最适合我的数据访问层架构。
我的解决方案有 3 层:
- 表示层 - ASP.net 应用程序
- 业务逻辑层 - C# 对象和逻辑
- 数据访问层 - 调用存储过程的函数。
我想更换数据访问层。
例如,如果我使用实体框架或 NHibernate,什么将确保稍后我能够替换该数据访问层而不需要更改业务逻辑层?
实体框架或 NHibernate 中的接口的使用从何而来?
I am really new at this and I am trying to find the best data access layer architecture for me.
I have 3 layers in my solution:
- Presentation layer - ASP.net application
- Business logic layer - c# objects and logic
- Data access layer - functions that call stored procedures.
I want replace the data access layer.
In case I use the Entity Framework or NHibernate, for example, what will ensure that later I would be able to replace that data access layer without making changes in the business logic layer?
Where comes the use of interfaces in the Entity Framework, or NHibernate?
发布评论
评论(3)
设计一个接口来映射您将在 DAL 中使用的所有关键方法。然后仅通过接口引用 DAL 类。这将通过将各层相互解耦来赋予其模块化性。
每当您需要交换所述DAL时,您只需插入一个实现所述接口的新DAL即可。您的其余代码不会因更改而变得更明智。
只是解决您的问题的一种方法。
Design an interface that maps out all key methods that you would use at your DAL. Then only reference the DAL classes by the interface. This will give it modularity by decoupling the layers from each other.
Whenever you need to swap the said DAL out, you just need to insert a new DAL that implements the said interface. The rest of your code will be none the wiser for the change.
Just one approach to your problem.
为了保留业务层,您还必须保留模型。因为业务和模型有着非常紧密的联系。
您可以更改是将模型映射到数据库的层。
NHibernate
和Entity Framework
4.1 都允许我们所说的 POCO 对象。 POCO 对象是纯 CLR 对象,不引用任何特定于持久性的类。也就是说:它不包含任何属性或基类,或将该类耦合到程序集的方法调用。使用 NHibernate 时,您可以使用 XML 文件或使用 Fluent NHibernate 的流畅方法将这些 POCO 类映射到数据库。在 EF4.1 中,您只能使用 Fluent 方法。您必须关心的一件事是
存储过程
的使用。这本质上会损害持久层替换。 EF4.1 POCO 方式目前不支持存储过程。 NHibernate 可能会,但我不确定。编辑
正如马修·考克斯提到的。当然,当涉及到 DAL 类时,就需要接口。因为CRUD操作在持久层之间会有所不同。这些接口将允许持久性替换。
例子:
In order to preserve the business layer you must keep the model as well. Because the business has a very tight connection to the model.
What you can change is the layer that maps your model to the database.
Both
NHibernate
andEntity Framework
4.1 allow what we call POCO objects. POCO objetcs are pure CLR objects that do not reference any persistence-specific classes. That is: It does not contain any attributes or base classes, or method calls that would couple this class to an assembly. While using NHibernate you can map these POCO classes to the database by using XML files or a fluent methodology using Fluent NHibernate. In EF4.1 you can only use the fluent methodology.One thing you have to concern about is the use of
stored procedures
. That is something that by nature compromises persistence layer substitution. EF4.1 POCO approach currently does not support stored procedures. NHibernate probably does but I'm not sure.EDIT
As Matthew Cox mentioned. Of course there will be need for interfaces when it comes to the DAL classes. Because CRUD operations will vary among persistence layers. These interfaces will allow for persistence substitution.
Example:
具体来说,nHibernate (3.0+) 和 EF 支持 LINQ,因此您可以通过代码创建一个简单的 IRepository 接口,该接口接受
Expression>
并避免使用具有 GetPersonByID、getPersonByName 等的存储库虽然这可能会妨碍您交换 ORM,但我认为您不会使用不支持 LINQ 的 ORM。这个界面可能看起来像这样(这不是一个完整的实现!这只是一个演示,真正的界面需要更好的改进!这只是我的东西)现在已经模拟了!这可能还需要实现 IDisposable 等):
但是,我想提一下人们在抽象 DAL 时忽略的一些事情。 此o/c仅是我的意见。
虽然抽象可以帮助你在未来“交换”DAL,但我会认真思考你是否能从中获得任何东西,除了创建遵循“最佳实践”和“人们说你应该做什么”的软件,另一方面搬起石头砸自己的脚。
当您完全抽象 DAL 时,您可能会失去其他 ORM 特定功能,这些功能实际上使一个 ORM 比另一个更好,甚至可能会丢失未来为了抽象而进行的性能优化。 i/e nHibernate 中的未来查询(在我看来这是一个巨大的功能),如果你将其抽象出来,你基本上会丢失它。您还可能会失去延迟初始化优化(选择 N+1 问题),因为您无法使用 Fetch (nHibernate) 或 Include (EF)。即使是像枚举支持这样的小事情(我相信 EF 仍然不支持)。
我还想补充一点,许多开发人员为了未来的变化而创建抽象,而实际上这些变化几乎永远不会发生。
因此,虽然我不是说不要抽象 DAL,因为它有很多优点,例如单元测试、解耦等(尽管您始终可以创建一个耦合的-to-dal 存储库,这将有助于单元测试),如果值得为某些实际上使 nhibernate/EF 比其他更好的功能付出代价,那么应该认真考虑。
Specifically nHibernate (3.0+) and EF support LINQ, as such you code create a simple IRepository interface which accepts an
Expression<Func<TItemType,bool>>
and avoid having repositories that have GetPersonByID, getPersonByName etc. While this might hinder you in swapping an ORM I think that you won't use an ORM that doesn't support LINQ.This interface might look something like this (this is NOT a complete implementation! this is just a demonstration, and the real interface will need better refinment! This is just something I've mocked up now! This might need to also need implement IDisposable, etc.):
I would, however, like to mention some things that people ignore when abstracting the DAL. This o/c is all my opinion.
While abstracting can help you "swap" the DAL in the future, I would think hard if you gain anything by it, except creating software that goes by "best practices" and what "people say you should do", and on the other hand shooting yourself in the foot.
When you abstract the DAL completely you might lose other ORM specific features which actually make one ORM better than the other, or even future performance optimizations for the sake of abstractions. i/e Future queries in nHibernate (which imo are a huge feature), which you basically lose if you abstract it away. You might also lose lazy initialization optimizations (Select N+1 problems) as you can't use Fetch (nHibernate) or Include (EF). Even small things like enum support (which I believe EF STILL doesn't support).
I would also like to add that a lot of developers create abstractions for the sake of future changes, while in reality these changes almost never happen.
So while I'm not saying don't abstract the DAL, because there are a lot of advantages like unit testing, decoupling etc. (although you can always create a coupled-to-dal repository which would help with unit testing), it's something that should be heavily considered if it's worth paying the paying the price of some features that actually make nhibernate/EF better than the other.