在构造函数c#中注入多个连接字符串

问题描述 投票:0回答:1

我有一个用例,我需要在我的数据访问层中使用多个连接字符串,并根据输入使用任何人。

目前,我有两个连接字符串,我已经在JSON中添加,然后我注入了两个。

是否有任何其他解决方案一次注入所有连接字符串,因为将来随着任何新数据库的引入,我必须在JSON中再添加一个连接字符串然后再次注入它?

StartUp类:

private static void Main(string[] args)
{
    ServiceCollection serviceCollection = new ServiceCollection();
    ConfigureServices(serviceCollection);

    IServiceProvider serviceProvider = 
    serviceCollection.BuildServiceProvider();
    serviceProvider.GetService<StudentApp>().Start();
}

private static void ConfigureServices(IServiceCollection 
serviceCollection)
{
    IConfigurationRoot configuration = GetConfiguration();
    Database database1 = new SqlDatabase(configuration.GetSection("Configuration:ConnectionString1").Value;
    Database database2 = new SqlDatabase(configuration.GetSection("Configuration:ConnectionString2").Value;

    // Here I am doing Multiple injections
    serviceCollection.AddSingleton(database1);
    serviceCollection.AddSingleton(database2);

    serviceCollection.AddOptions();
    serviceCollection.Configure<AppSettings(configuration.GetSection("Configuration"));
    serviceCollection.AddSingleton(configuration);

    serviceCollection.AddTransient<IStudentDataAccess,StudentDataAccess>();
    serviceCollection.AddTransient<StudentApp>();
}

private static IConfigurationRoot GetConfiguration()
{
    return new ConfigurationBuilder()
       .AddJsonFile("appsettings.json", optional: true)
       .Build();
}

StudentApp课程:

private readonly IStudentDataAccess _dataAccess;
private readonly AppSettings _config;
private readonly Database _database1;
private readonly Database _database2;

public StudentApp(IStudentDataAccess dataAccess,IOptions<AppSettings> 
config, Database database1, Database database2)
{
     _dataAccess= dataAccess;
     _config = config.Value;
     _database1 = database1;
     _database2 = database2;
}

public void Start()
{
    int count= _dataAccess.GetStudentCount(deptId);
}

DataAccess类:

public interface IStudentDataAccess 
{
    int GetStudentCount(int deptId);
}

public class StudentDataAccess : IStudentDataAccess 
{
    private readonly AppSettings _config;
    private readonly Database _database1;
    private readonly Database _database2;
    public StudentDataAccess (IOptions<AppSettings> config, Database 
    database1,Database database2)
    {
         _config = config.Value;
         _database1 = database1;
         _database2 = database2;
    }

    public int GetStudentCount(int deptId)
    {
        // Execute queries either by Database1 or 2.
    }
 }

使用的数据库类来自Microsoft.Practices.EnterpriseLibrary.Data。如何避免为不同的连接字符串创建多个Singleton类?

有帮助吗?

c# dependency-injection solid-principles
1个回答
0
投票

您可以将连接字符串保存为appsettings.json中的数组:

{
  ...
  "ConnectionStrings": [
    {
      "Name": "ConnectionString1",
      "Value":  "some value"
    },
    {
      "Name": "ConnectionString1",
      "Value": "some value"
    }
  ]
}

并使用Options pattern将它们映射到某个类:

public class ConnectionStringOptions
{
    public ConnectionString[] ConnectionStrings { get; set; }
}
public class ConnectionString
{
    public string Name { get; set; }
    public string Value { get; set; }
}

然后,您可以拥有这样的界面:

public interface IDatabaseProvider
{
    IEnumerable<Database> GetDatabases();
    Database GetDatabase(string name);
}

与这样的实现

public class DatabaseProvider : IDatabaseProvider
{
    private readonly ConnectionStringOptions _options;

    public DatabaseProvider(IOptions<ConnectionStringOptions> optionsAccessor)
    {
        this._options = optionsAccessor.Value;
    }

    public IEnumerable<Database> GetDatabases()
    {
        foreach (ConnectionString connectionString in this._options.ConnectionStrings)
            yield return new SqlDatabase(connectionString.Value);
    }

    public Database GetDatabase(string name)
    {
        string connectionString = this._options.ConnectionStrings.SingleOrDefault(x => x.Name == name).Value;
        return new SqlDatabase(connectionString);
    }
}

现在你只需注册IDatabaseProvider

serviceCollection.AddTransient<IDatabaseProvider, DatabaseProvider>()

并根据需要将其注入您的服务中。例如:

public class StudentApp
{
    private readonly IEnumerable<Database> _databases;

    public StudentApp(IStudentDataAccess dataAccess, IDatabaseProvider databasesProvider)
    {
        //Or get just the one you want by name
        this._databases = databasesProvider.GetDatabases();

        // ...
    }

    // ...
}

更新:选项模式的代码段:

serviceCollection.Configure<ConnectionStringOptions>(configuration.GetSection("ConnectionStrings”));
© www.soinside.com 2019 - 2024. All rights reserved.