Why use database factory in asp.net mvc?

2019-07-20 15:53发布

Recently I have worked with asp.net mvc and I have seen in sample project is using Database Factory class. How can you explain for me why use it ?

IDatabaseFactory class

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

DatabaseFactory 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();
    }
}

1条回答
看我几分像从前
2楼-- · 2019-07-20 16:35

This is an example of an Abstract Factory design pattern. The idea is to create a seam to provide loose coupling between the classes so another type of context could be swapped, either for testing purposes or to extend the application.

Generally speaking, a factory is a way to manage short-lived dependencies, such as database connections. Typically, a framework exposes a way to inject an instance of the factory and then the framework can work with it based on an interface (in this case IDatabaseFactory) as a contract between the framework, and the framework user. The framework will have code that looks something like this:

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
    }
}

The service can then be instantiated for a much longer lifetime than the context that is created by the factory. What's more is that the context is always properly disposed in this scenario.

Now, the main benefit from doing this is that you can swap the DatabaseFactory with an alternate implementation (commonly referred to as the 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();
    }
}

Assuming that AlternateDataContext inherits (or implements) EFMVCDataContex, MyDatabaseFactory can be swapped apples-for-apples with DatabaseFactory without making any changes to SomeService.

MyDatabaseFactory could be coded with a connection string in the constructor, giving you a way to connect to alternate databases, for example.

Of course, another great benefit of doing this is to create a mock implementation of IDatabaseFactory that can be used to test the DoSomething method. In a unit test, SomeService (the class under test) should be the only real class being used, IDatabaseFactory should be a mock (which could either be done by hand coding a class, or using a mocking framework).

查看更多
登录 后发表回答