为什么在 asp.net mvc 中使用数据库工厂?

Why use database factory in asp.net mvc?

最近我使用了 asp.net mvc,我在示例项目中看到正在使用数据库工厂 class。您如何向我解释为什么要使用它?

IDatabaseFactory class

public interface IDatabaseFactory : IDisposable
{
    EFMVCDataContex Get();
}

数据库工厂class

public class DatabaseFactory : Disposable, IDatabaseFactory
{
    private EFMVCDataContex dataContext;
    public EFMVCDataContex Get()
    {
        return dataContext ?? (dataContext = new EFMVCDataContex());
    }
    protected override void DisposeCore()
    {
        if (dataContext != null)
            dataContext.Dispose();
    }
}

这是一个 Abstract Factory 设计模式的例子。这个想法是创建一个接缝以提供 classes 之间的松散耦合,以便可以交换另一种类型的上下文,无论是出于测试目的还是为了扩展应用程序。

一般来说,工厂是一种管理短期依赖项(例如数据库连接)的方法。通常,框架公开了一种注入工厂实例的方法,然后框架可以基于接口(在本例中为 IDatabaseFactory)作为框架与框架用户之间的契约来使用它。该框架将具有如下所示的代码:

public interface ISomeService
{
    void DoSomething();
}

public class SomeService()
{
    private readonly IDatabaseFactory factory;

    // The factory is injected through the constructor
    public SomeService(IDatabaseFactory factory)
    {
        this.factory = factory;
    }

    public void DoSomething()
    {
        using (EFMVCDataContex context = this.factory.Get())
        {
            // Run a LINQ query here using the context

        } // This bracket disposes the context
    }
}

然后可以实例化服务,其生命周期比工厂创建的上下文长得多。更重要的是,上下文总是在这种情况下得到妥善处理。

现在,这样做的主要好处是您可以将 DatabaseFactory 替换为替代实现(通常称为 Liskov Substitution Principle):

public class MyDatabaseFactory : Disposable, IDatabaseFactory
{
    private EFMVCDataContex dataContext;
    public EFMVCDataContex Get()
    {
        return dataContext ?? (dataContext = new AlternateDataContext());
    }

    protected override void DisposeCore()
    {
        if (dataContext != null)
            dataContext.Dispose();
    }
}

假设 AlternateDataContext 继承(或实现)EFMVCDataContex,MyDatabaseFactory 可以与 DatabaseFactory 同类对换,而无需对 SomeService 进行任何更改。

MyDatabaseFactory 可以在构造函数中使用连接字符串进行编码,例如,为您提供一种连接到备用数据库的方法。

当然,这样做的另一大好处是创建可用于测试 DoSomething 方法的 IDatabaseFactory 的模拟实现。在单元测试中,SomeService(被测的 class)应该是唯一真正使用的 class,IDatabaseFactory 应该是一个模拟(可以通过手动编码 class,或使用模拟框架)。