Microsoft.AspNetCore.All : v2.0.3 | Чудний : v1.50.2
Я не впевнений, чи правильно використовую найкращі практики чи ні, але роблю це таким чином, щоб обробляти кілька рядків підключення.
Це просто, якщо у вас є лише 1 рядок з’єднання
Startup.cs
using System.Data;
using System.Data.SqlClient;
namespace DL.SO.Project.Web.UI
{
public class Startup
{
public IConfiguration Configuration { get; private set; }
public void ConfigureServices(IServiceCollection services)
{
string dbConnectionString = this.Configuration.GetConnectionString("dbConnection1");
services.AddTransient<IDbConnection>((sp) => new SqlConnection(dbConnectionString));
services.AddScoped<IDiameterRepository, DiameterRepository>();
}
}
}
DiameterRepository.cs
using Dapper;
using System.Data;
namespace DL.SO.Project.Persistence.Dapper.Repositories
{
public class DiameterRepository : IDiameterRepository
{
private readonly IDbConnection _dbConnection;
public DiameterRepository(IDbConnection dbConnection)
{
_dbConnection = dbConnection;
}
public IEnumerable<Diameter> GetAll()
{
const string sql = @"SELECT * FROM TABLE";
return _dbConnection.Query<Diameter>(sql);
}
}
}
Проблеми, якщо у вас більше 1 рядка підключення
Оскільки Dapper
використовує IDbConnection
, вам потрібно придумати спосіб диференціювати різні підключення до бази даних.
Я спробував створити декілька інтерфейсів, "успадкованих" від IDbConnection
, що відповідають різним з'єднанням з базою даних, і вводити SqlConnection
з різними рядками підключення до бази даних Startup
.
Це не вдалося, оскільки SqlConnection
успадковує DbConnection
та DbConnection
доповнює не тільки, IDbConnection
але й Component
клас. Отже, ваші користувацькі інтерфейси не зможуть використовувати лише SqlConnection
імплементацію.
Я також намагався створити власний DbConnection
клас, який приймає різні рядки з'єднання. Це занадто складно, тому що вам доведеться реалізувати всі методи з DbConnection
класу. Ви втратили допомогу від SqlConnection
.
Що я в підсумку роблю
- Протягом
Startup
я завантажив усі значення рядків підключення до словника. Я також створив enum
для всіх імен підключення до бази даних, щоб уникнути магічних рядків.
- Я ввів словник як Singleton.
- Замість того
IDbConnection
, IDbConnectionFactory
щоб вводити , я створив і ввів це як Перехідний для всіх сховищ. Тепер усі сховища беруть IDbConnectionFactory
замість IDbConnection
.
- Коли правильно вибрати зв’язок? У конструкторі всіх сховищ! Щоб зробити речі чистими, я створив базові класи репозиторію і маю сховища, що успадковуються від базових класів. Правильний вибір рядка підключення може відбуватися в базових класах.
DatabaseConnectionName.cs
namespace DL.SO.Project.Domain.Repositories
{
public enum DatabaseConnectionName
{
Connection1,
Connection2
}
}
IDbConnectionFactory.cs
using System.Data;
namespace DL.SO.Project.Domain.Repositories
{
public interface IDbConnectionFactory
{
IDbConnection CreateDbConnection(DatabaseConnectionName connectionName);
}
}
DapperDbConenctionFactory - моя власна реалізація на заводі
namespace DL.SO.Project.Persistence.Dapper
{
public class DapperDbConnectionFactory : IDbConnectionFactory
{
private readonly IDictionary<DatabaseConnectionName, string> _connectionDict;
public DapperDbConnectionFactory(IDictionary<DatabaseConnectionName, string> connectionDict)
{
_connectionDict = connectionDict;
}
public IDbConnection CreateDbConnection(DatabaseConnectionName connectionName)
{
string connectionString = null;
if (_connectDict.TryGetValue(connectionName, out connectionString))
{
return new SqlConnection(connectionString);
}
throw new ArgumentNullException();
}
}
}
Startup.cs
namespace DL.SO.Project.Web.UI
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
var connectionDict = new Dictionary<DatabaseConnectionName, string>
{
{ DatabaseConnectionName.Connection1, this.Configuration.GetConnectionString("dbConnection1") },
{ DatabaseConnectionName.Connection2, this.Configuration.GetConnectionString("dbConnection2") }
};
services.AddSingleton<IDictionary<DatabaseConnectionName, string>>(connectionDict);
services.AddTransient<IDbConnectionFactory, DapperDbConnectionFactory>();
services.AddScoped<IDiameterRepository, DiameterRepository>();
}
}
}
DiameterRepository.cs
using Dapper;
using System.Data;
namespace DL.SO.Project.Persistence.Dapper.Repositories
{
public class DiameterRepository : DbConnection1RepositoryBase, IDiameterRepository
{
public DiameterRepository(IDbConnectionFactory dbConnectionFactory)
: base(dbConnectionFactory) { }
public IEnumerable<Diameter> GetAll()
{
const string sql = @"SELECT * FROM TABLE";
return base.DbConnection.Query<Diameter>(sql);
}
}
}
DbConnection1RepositoryBase.cs
using System.Data;
using DL.SO.Project.Domain.Repositories;
namespace DL.SO.Project.Persistence.Dapper
{
public abstract class DbConnection1RepositoryBase
{
public IDbConnection DbConnection { get; private set; }
public DbConnection1RepositoryBase(IDbConnectionFactory dbConnectionFactory)
{
this.DbConnection = dbConnectionFactory.CreateDbConnection(DatabaseConnectionName.Connection1);
}
}
}
Тоді для інших сховищ, які потребують розмови з іншими підключеннями, ви можете створити для них інший базовий клас сховища.
using System.Data;
using DL.SO.Project.Domain.Repositories;
namespace DL.SO.Project.Persistence.Dapper
{
public abstract class DbConnection2RepositoryBase
{
public IDbConnection DbConnection { get; private set; }
public DbConnection2RepositoryBase(IDbConnectionFactory dbConnectionFactory)
{
this.DbConnection = dbConnectionFactory.CreateDbConnection(DatabaseConnectionName.Connection2);
}
}
}
using Dapper;
using System.Data;
namespace DL.SO.Project.Persistence.Dapper.Repositories
{
public class ParameterRepository : DbConnection2RepositoryBase, IParameterRepository
{
public ParameterRepository (IDbConnectionFactory dbConnectionFactory)
: base(dbConnectionFactory) { }
public IEnumerable<Parameter> GetAll()
{
const string sql = @"SELECT * FROM TABLE";
return base.DbConnection.Query<Parameter>(sql);
}
}
}
Сподіваюся, вся ця допомога.