数据访问层-模块化和可重用性

问题描述

| 我真的很新,我正在尝试为我找到最好的数据访问层体系结构。 我的解决方案有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确实比其他功能更好的功能的代价,就应该认真考虑这一点。