我有一个用例,我需要在我的数据访问层中使用多个连接字符串,并根据输入使用任何人。
目前,我有两个连接字符串,我已经在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类?
有帮助吗?
您可以将连接字符串保存为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”));