ASP.NET的DAL和BLL首选设计模式方法

4
我正在开发几个小型ASP.NET应用程序,想知道您在项目中使用哪种模式或方法。我的项目涉及数据库,使用数据访问和业务逻辑层。
到目前为止,我一直在使用以下数据访问方法(我在某本书中看到并喜欢它):
对于DAL层: 创建一个抽象类,定义要实现的所有数据库操作方法。 这个抽象类将包含一个静态“Instance”属性,如果instance == null,它将加载所需类型的实例(Activator.CreateInstance)。
创建实现此抽象类的类,实现将根据使用的数据库(SQL、mySQL等)进行。 通过这种方式,我可以根据使用的数据库创建不同的实现。
对于BLL层: 封装所有检索字段的类,并调用DAL类的静态方法。
这是一个好的方法吗?在这种情况下,您更喜欢使用什么?
3个回答

2
通过使用静态类方法,您可以隐藏对这些组件的依赖并限制将来的选项(例如,您无法对业务层进行子类化)。
不要使用单例和静态方法来访问数据和业务层,而是考虑将业务层类更改为需要数据访问实例,并在您的顶级应用程序中保留一个业务层实例。
public class Global HttpApplication {

    // This would really be a property
    // It's also unfortunate this has to be static, but you're stuck with
    // default constructors for ASP.NET pages, so there's no alternative.
    public static BusinessLayerClass BusinessLayer;

    protected void Application_Start(object sender, EventArgs e) {
         AbstractDataAccessLayer dataAccess = new ConcreteDataAccessLayer();
         Global.BusinessLayer = new BusinessLayerClass(dataAccess);             
    }
}

网页可以像这样使用它:
public void PerformSomeBusinessFunction() {
    Global.BusinessLayer.DoSomething();
}

这表明您的业务层需要数据访问,提供了一个方便的地方来指定将使用哪种类型的数据访问对象,并为您使用不同的创建策略铺平了道路,如果必要的话。例如,您可以提供一个数据访问工厂,而不是在所有业务层之间共享单个实例。

这里的一般原则被称为“依赖注入”(有时也被称为“控制反转”,这是DI背后更通用的原则。)

如果手动进行依赖注入变得繁琐,请考虑使用依赖注入框架(人们也称之为“IoC容器”)。


什么是顶层应用程序? - luppi
我可能只应该说“应用程序”。在.NET中,这是您的可执行文件或HttpApplication类(Global)。 - Jeff Sternal
如果我为每个模块定义DAL和BLL层呢? 假设我有3个模块:用户、评论、博客文章,每个模块都有自己的DAL和BLL类(当然,它们可以使用不同的数据库提供程序),这将要求我在global.aspx中定义许多属性。这样做是否高效? - luppi
这取决于你所说的“高效”是什么意思,但如果你超过了一小部分这样的类和属性,或者你发现自己有更复杂的对象图,那么你应该考虑使用依赖注入框架。大多数框架提供一个单一的通用工厂对象,你可以像这样调用它:var userBusinessLayer = Container.Resolve<IUserBusinessLayer>()。 - Jeff Sternal
我遇到了一个问题,无法使用构造函数来创建BusinessLayer对象,因为如果我使用ObjectDataSource,就无法使用它的TypeName属性。 - luppi

1

好的,我来告诉你一些使用方法上的陷阱,以及我通常的做法。

陷阱

你的DAL实例属性似乎是一种聪明而奇怪的单例模式。你应该记住,对于你的Web服务器的请求可以被异步处理,所以如果你的Activator.CreateInstance调用需要一些时间,这可能会导致一些问题。

我猜你的BLL层也有同样的问题。最好在应用程序启动事件(无法记住确切名称)上执行此类初始化。

你基本上使用的是DI原则和存储库模式。两者都很棒,可以允许修改和测试,但是,由于你的抽象类将位于DAL中,而你的BLL方法将调用DAL类,因此你的BLL需要知道DAL。这可能会成为一个问题。你可以创建一个中间库,其中包含对抽象类的接口。

我通常的做法

我真的不喜欢应用程序中的“层”,因为往往很难区分不同类型的功能以及它们应该了解其他层的方向。我使用另一种方法,我不确定它是否被称为任何东西,但我称之为依赖环 :) 基本上,它就像一个飞镖板,其中最内部的程序集将不知道最外部的程序集。

在您典型的博客引擎 Web 应用程序中,我会做这样的事情:

BlogEngine.Core 包含各种项目的 POCO 实体(例如 PostUserComment 等等),以及各种服务接口。这些服务可以包括 IEmailServiceIBlogRepositoryIUserManagement 等等... 现在我创建了一个 BlogEngine.Infrastructure.Persistence 组件,它知道如何使用 .Core 并实现 IBlogRepository。对于所有其他服务,我也是这样做的。
现在 - 您的 BlogEngine.Web 只需要引用您的 .Core 组件和一个 IoC 框架组件,该框架将处理所有依赖项。如果我想要更新帖子,我可以执行 myIOC.GetInstance<IBlogRepository>().SaveOrUpdatePost(newPost);
假设您想要在人们在他们的博客上发布评论时通知作者。您可以在 .Core 中实现此逻辑作为一个 Notifier 类。该类可以解析 IEmailService,然后发送任何您需要的电子邮件。

重点是:您有一个核心,它应该永远不会随着您的域而改变。然后您有仅知道核心的基础结构组件。您的Web应用程序知道核心和IOC框架-并且您拥有了解所有内容的IOC,并被允许这样做:)如果您需要进行更改,则很可能是在基础结构组件中,因此您只需更新IOC设置并实现哪些

我希望这讲得通,如果不能,请留下评论,我会尽力解释 :)

祝你好运


1

这是一个很好的方法。我也在使用这种方法。我使用企业库来进行数据访问层。最近我发现使用L2S对于数据访问层非常有用。

我也推荐使用NHibernate。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接