问题描述
|
我真的很新,我正在尝试为我找到最好的数据访问层体系结构。
我的解决方案有3层:
表示层-ASP.net应用程序
业务逻辑层-C#对象和逻辑
数据访问层-调用存储过程的函数。
我想替换数据访问层。
例如,在使用实体框架或NHibernate的情况下,将如何确保以后在不更改业务逻辑层的情况下替换该数据访问层呢?
实体框架或NHibernate中使用接口的地方在哪里?
解决方法
为了保留业务层,您还必须保留模型。因为企业与模型之间的联系非常紧密。
您可以更改的是将模型映射到数据库的层。
NHibernate
和Entity Framework
4.1都允许我们称为POCO对象。 POCO objetcs是纯CLR对象,不引用任何特定于持久性的类。即:它不包含任何将此类与程序集耦合的属性或基类或方法调用。使用NHibernate时,您可以使用XML文件或使用Fluent NHibernate的流畅方法将这些POCO类映射到数据库。在EF4.1中,您只能使用流利的方法。
您需要担心的一件事是使用stored procedures
。从本质上讲,这是对持久层替换的折衷。 EF4.1 POCO方法当前不支持存储过程。 NHibernate可能会这样做,但是我不确定。
编辑
正如马修·考克斯(Matthew Cox)所述。当然,对于DAL类,将需要接口。因为CRUD操作在持久层之间会有所不同。这些接口将允许持久性替换。
例:
public class IPersonDAL {
IList<Person> GetPeople();
void InsertPerson(Person person);
...
}
,设计一个接口,该接口映射出将在DAL中使用的所有关键方法。然后仅通过接口引用DAL类。通过将各个层彼此解耦,可以提供模块化。
每当您需要换出上述DAL时,您只需插入一个实现上述接口的新DAL。您的其余代码对更改而言都不是明智之举。
只是解决问题的一种方法。
,特别是nHibernate(3.0+)和EF支持LINQ,因此您的代码创建了一个简单的IRepository接口,该接口接受一个Expression<Func<TItemType,bool>>
,并避免使用具有GetPersonByID,getPersonByName等的存储库。尽管这可能会妨碍您交换ORM,但我认为您会\不要使用不支持LINQ的ORM。
该接口可能看起来像这样(这不是完整的实现!这只是一个演示,而真实的接口将需要更好的改进!这只是我现在所模拟的东西!这可能还需要实现IDisposable等):
interface IRepository<TPersistant>
{
void Save(TPersistant item);
void Delete(TPersistant item);
TPersistant Find(Expression<Func<TPersistant,bool>> predicate);
// maybe findOne or findMany
// maybe something like this
IQueryable<TPersistant> Query();
/* Other stuff like updating,transactions,commiting,etc.*/
}
但是,我想提一些人们在抽象DAL时忽略的事情。这是我的全部意见。
虽然抽象可以帮助您将来“交换” DAL,但我想如果您从中获得任何好处,除了创建遵循“最佳实践”和“人们应该做什么”的软件之外, ,另一方面用脚射击自己。
当您完全抽象DAL时,您可能会丢失其他ORM特定的功能,这些功能实际上会使一个ORM比另一个更好,甚至为了抽象起见,甚至将来会进行性能优化。 i / e nHibernate中的Future查询(哪个imo是一个巨大的功能),如果将其抽象化,则基本上会丢失。您也可能会失去懒惰的初始化优化(选择N + 1个问题),因为您无法使用提取(nHibernate)或包含(EF)。甚至是枚举支持之类的小东西(我相信EF STILL也不支持)。
我还要补充一点,很多开发人员为了将来的更改而创建抽象,而实际上这些更改几乎从未发生过。
因此,虽然我不是说不要抽象DAL,但因为它具有许多优点,例如单元测试,去耦等。(尽管您始终可以创建一个耦合到节点的存储库,这将有助于单元测试) ,如果值得付出某些使nhibernate / EF确实比其他功能更好的功能的代价,就应该认真考虑这一点。