Dependency Injection for DAL with multiple databas

2019-07-22 20:37发布

I have an application that uses Structuremap for DI for both my business and DAL layer. Up to this point, I have had a single DAL per environment that I have been working on. So I would grab it from the config and use that value for all my connections. An example of this is.

 using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Database"].ToString()))
{
    //Do a call to db here.
}

I am calling this method using structure map as follows.

 ObjectFactory.GetInstance<IDALManager>().MethodName();

Now I have a new feature where I want to allow the users to make change in a dev environment and then push a button to elevate it to test or prod environment. Therefore my connectionstring for the DAL manager will need to be able to change. I also would like to keep all the connection string access in the DAL and not in the other layers. I am looking for advice on how to do this or what design patterns to look into for this.

UPDATED INFORMATION The user will determine which connection string needs to be used. For example, they will be moving data from dev to test, they will select a source and a destination.

string source = \\user selection from combobox.
if (source == "DEV")
{
     //Instantiate dev instance of manager
}
if (source == "TEST")
{ 
     //Instantiate Test Instance of manager.
}

1条回答
爷的心禁止访问
2楼-- · 2019-07-22 21:11

You need an abstract factory. Take a look at the answer in this question for some examples.

In your particular case, your abstract factory interface should look like this:

public interface IDALManagerFactory
{
    IDALManager Create(string environment);
}

You need to create an implementation of this interface that creates a "DAL Manager" with the appropriate connection string.

To be able to do this, you need the connection string to be injected into the constructor of your class like this:

public class MyDalManager: IDALManager
{
    private readonly string connectionString;

    public MyDalManager(string connectionString)
    {
        this.connectionString = connectionString;
    }

    public MyMethod()
    {
        //..

        using (SqlConnection con = new SqlConnection(connectionString))
        {
            //Do a call to db here.
        }
    }
}

Now the implementation of the factory would look something like this:

public class DALManagerFactory : IDALManagerFactory
{
    public IDALManager Create(string environment)
    {
         if(environment == "DEV")
             return new MyDalManager(
                 ConfigurationManager.ConnectionStrings["Database"].ToString());
         //...
    }
}

This factory class should live in the Composition Root. You can also access the container inside this factory class to create the "DAL Manager".

Now, the class that needs access to the appropriate "DAL Manager" should have a IDALManagerFactory injected into its constructor, and it would use such factory to create a IDALManager by invoking the Create method passing the environment name.

Please note that in your code, you are accessing the connection string in the DAL layer. You really should access such information in the composition root only.

查看更多
登录 后发表回答