Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 数据访问层-模块化和可重用性_C#_.net_Design Patterns - Fatal编程技术网

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

C# 数据访问层-模块化和可重用性,c#,.net,design-patterns,C#,.net,Design Patterns,在这方面我是个新手,我正在努力为自己找到最好的数据访问层体系结构。 我的解决方案中有3层: 表示层-ASP.net应用程序 业务逻辑层-c对象和逻辑 数据访问层-调用存储过程的函数。 我想更换数据访问层 例如,在我使用实体框架或NHibernate的情况下,如何确保以后我能够在不更改业务逻辑层的情况下替换该数据访问层? 实体框架或NHibernate中接口的使用从何而来?设计一个接口,该接口映射出您将在DAL中使用的所有关键方法。然后仅通过接口引用DAL类。这将通过将各层彼此分离来实现模块化 每

在这方面我是个新手,我正在努力为自己找到最好的数据访问层体系结构。 我的解决方案中有3层:

表示层-ASP.net应用程序 业务逻辑层-c对象和逻辑 数据访问层-调用存储过程的函数。 我想更换数据访问层

例如,在我使用实体框架或NHibernate的情况下,如何确保以后我能够在不更改业务逻辑层的情况下替换该数据访问层?
实体框架或NHibernate中接口的使用从何而来?

设计一个接口,该接口映射出您将在DAL中使用的所有关键方法。然后仅通过接口引用DAL类。这将通过将各层彼此分离来实现模块化

每当您需要交换所述DAL时,您只需要插入一个实现所述接口的新DAL。对于更改,您的代码的其余部分将不再明智


只有一种方法可以解决您的问题。

设计一个界面,列出您在DAL中使用的所有关键方法。然后仅通过接口引用DAL类。这将通过将各层彼此分离来实现模块化

每当您需要交换所述DAL时,您只需要插入一个实现所述接口的新DAL。对于更改,您的代码的其余部分将不再明智


只有一种方法可以解决您的问题。

为了保留业务层,您还必须保留模型。因为业务与模型有着非常紧密的联系

可以更改的是将模型映射到数据库的图层

NHibernate和实体框架4.1都允许我们称之为POCO对象。POCO OBJETC是纯CLR对象,不引用任何特定于持久性的类。也就是说:它不包含将此类耦合到程序集的任何属性、基类或方法调用。使用NHibernate时,您可以使用XML文件或使用fluent NHibernate的fluent方法将这些POCO类映射到数据库。在EF4.1中,您只能使用fluent方法

您必须关心的一件事是存储过程的使用。这是一种本质上会影响持久性层替换的东西。EF4.1 POCO方法目前不支持存储过程。可能是的,但我不确定

编辑

正如马修·考克斯所提到的。当然,当涉及到DAL类时,将需要接口。因为CRUD操作在持久性层之间会有所不同。这些接口将允许持久性替换

例如:

public class IPersonDAL {
    IList<Person> GetPeople();
    void InsertPerson(Person person);
    ...
}

为了保留业务层,还必须保留模型。因为业务与模型有着非常紧密的联系

可以更改的是将模型映射到数据库的图层

NHibernate和实体框架4.1都允许我们称之为POCO对象。POCO OBJETC是纯CLR对象,不引用任何特定于持久性的类。也就是说:它不包含将此类耦合到程序集的任何属性、基类或方法调用。使用NHibernate时,您可以使用XML文件或使用fluent NHibernate的fluent方法将这些POCO类映射到数据库。在EF4.1中,您只能使用fluent方法

您必须关心的一件事是存储过程的使用。这是一种本质上会影响持久性层替换的东西。EF4.1 POCO方法目前不支持存储过程。可能是的,但我不确定

编辑

正如马修·考克斯所提到的。当然,当涉及到DAL类时,将需要接口。因为CRUD操作在持久性层之间会有所不同。这些接口将允许持久性替换

例如:

public class IPersonDAL {
    IList<Person> GetPeople();
    void InsertPerson(Person person);
    ...
}

具体来说,nHibernate 3.0+和EF支持LINQ,因此您可以编写一个简单的IRepository接口,该接口接受表达式并避免存储库包含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时,你可能会 e其他特定于ORM的特性,这些特性实际上使一个ORM比另一个更好,甚至为了抽象而对未来的性能进行优化。i/e nHibernate中的未来查询imo是一个巨大的功能,如果将其抽象掉,基本上会丢失它。由于无法使用Fetch-nHibernate或Include-EF,您还可能会丢失延迟初始化优化选择N+1问题。即使是像enum支持这样的小东西,我相信EF仍然不支持

我还想补充一点,许多开发人员为了将来的更改而创建抽象,而实际上这些更改几乎从未发生过


因此,虽然我不是说不要抽象DAL,因为它有很多优点,比如单元测试、解耦等。尽管您总是可以创建一个耦合到DAL的存储库,这将有助于单元测试,如果值得为使nhibernate/EF比其他功能更好的某些功能付出代价的话,这是一个值得认真考虑的问题。

特别是nhibernate 3.0+和EF支持LINQ,因此,您可以通过代码创建一个简单的IRepository接口,该接口接受表达式,并避免存储库包含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中的未来查询imo是一个巨大的功能,如果将其抽象掉,基本上会丢失它。由于无法使用Fetch-nHibernate或Include-EF,您还可能会丢失延迟初始化优化选择N+1问题。即使是像enum支持这样的小东西,我相信EF仍然不支持

我还想补充一点,许多开发人员为了将来的更改而创建抽象,而实际上这些更改几乎从未发生过


因此,虽然我不是说不要抽象DAL,因为它有很多优点,比如单元测试、解耦等。尽管您总是可以创建一个耦合到DAL的存储库,这将有助于单元测试,如果值得为使nhibernate/EF比其他功能更好的某些功能付出代价的话,这是一个值得认真考虑的问题。

与POCO有什么关系吗?POCO解决了这个问题吗?@Naor:Matthew指的是DAL层。在DAL层,您确实需要接口。与POCO相关的是您从DAL层传递和接收的模型对象。+1 DAL层需要实现接口,但它们应该经常与使用者一起在外部定义。与POCO有任何关系吗?POCO解决了这个问题吗?@Naor:Matthew指的是DAL层。在DAL层,您确实需要接口。与POCO相关的是您从DAL层传递和接收的模型对象。+1 DAL层需要实现接口,但它们应该经常与使用者一起在外部定义。因此,您所说的是,在数据访问层中,我实际上需要模型对象,接口和ef/nhibernate类?@Naor:更清楚地说:在模型层上,您将拥有表示数据库的实体。在您的业务层上,您将拥有您的业务逻辑。在此层上,您将引用模型层,并通过表示DAL的接口对其进行操作。如果您更换了数据库,那么到目前为止我提到的所有内容都不需要更换。需要的另一层是实现这些接口并将POCO类从模型映射到数据库的层。该层可能需要在未来的数据库中替换,以获取有用的信息!最后要确定的是,在业务逻辑层中,我也有表示来自db的数据的对象,但是这些对象在逻辑中使用,它们不是POCO。因此,过程将是:首先使用DAL从db加载数据,然后将数据转换为模型层的POCO对象,最后将POCO对象转换为业务对象。这是正确的顺序吗?那么你说的是,在数据访问层中,我实际上需要模型对象、接口和ef/nhibernate类
s?@Naor:更清楚地说:在模型层上,您将拥有表示数据库的实体。在您的业务层上,您将拥有您的业务逻辑。在此层上,您将引用模型层,并通过表示DAL的接口对其进行操作。如果您更换了数据库,那么到目前为止我提到的所有内容都不需要更换。需要的另一层是实现这些接口并将POCO类从模型映射到数据库的层。该层可能需要在未来的数据库中替换,以获取有用的信息!最后要确定的是,在业务逻辑层中,我也有表示来自db的数据的对象,但是这些对象在逻辑中使用,它们不是POCO。因此,过程将是:首先使用DAL从db加载数据,然后将数据转换为模型层的POCO对象,最后将POCO对象转换为业务对象。这是正确的顺序吗?