Я разрабатывал приложение, которое использует различные подключения к данным (например, базу данных, остальные вызовы API, файлы конфигурации JSON) в C #.В настоящее время я пытаюсь создать разумную абстракцию уровня доступа к данным, которая позволила бы легко переключаться между ними.Для каждого из них требуются разные параметры подключения, а также они работают по-разному.
Я рассмотрел пример шаблона репозитория, но он не совсем соответствует моим потребностям.Я хочу иметь возможность определить шаблон запроса, который я могу параметризировать, и этот запрос сможет обрабатывать параметры.Пример того, что у меня сейчас есть:
public interface IQuery<TResult>
{
}
public interface IQueryHandler<TQuery, TResult>
where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
public class DatabaseQuery<TResult> : IQuery<IEnumerable<TResult>>
{
public string ConnectionString { get; set; }
public string CommandText { get; set; }
}
public class DatabaseConnection<TQuery, TResult> : IQueryHandler<TQuery, IEnumerable<TResult>>
where TQuery : DatabaseQuery<TResult>
{
public IEnumerable<TResult> Handle(TQuery query)
{
var results = new List<TResult>();
using (var connection = new SqlConnection(query.ConnectionString))
using (var command = new SqlCommand(query.CommandText, connection))
{
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
results.Add(...
}
}
}
return results;
}
}
public class JsonQuery<TResult> : IQuery<IEnumerable<TResult>>
{
public string FileLocation { get; set; }
public Func<TResult, bool> Condition { get; set; }
}
public class JsonConnection<TQuery, TResult> : IQueryHandler<TQuery, IEnumerable<TResult>>
where TQuery : JsonQuery<TResult>
{
public IEnumerable<TResult> Handle(TQuery query)
{
var text = File.ReadAllText(query.FileLocation);
return Deserialize<TResult>(text).Results.Where(query.Condition);
}
}
public interface IQueryBuilder<TQuery, TParameters>
{
TQuery Build(TParameters parameters);
}
public class GetAccountsByStatusAndBalanceHigherThanQueryParameters
{
public string Status { get; set; }
public decimal Balance { get; set; }
}
public class GetAccountsByStatusAndBalanceHigherThan_DatabaseQueryBuilder :
IQueryBuilder<DatabaseQuery<Account>, GetAccountsByStatusAndBalanceHigherThanQueryParameters>
{
public DatabaseQuery<Account> Build(GetAccountsByStatusAndBalanceHigherThanQueryParameters parameters)
{
return new DatabaseQuery<Account>()
{
ConnectionString = "connString",
CommandText = $"SELECT * FROM Accounts WHERE Status = {parameters.Status} AND Balance = {parameters.Balance}"
};
}
}
public class GetAccountsByStatusAndBalanceHigherThan_JsonQueryBuilder
: IQueryBuilder<JsonQuery<Account>, GetAccountsByStatusAndBalanceHigherThanQueryParameters>
{
public JsonQuery<Account> Build(GetAccountsByStatusAndBalanceHigherThanQueryParameters parameters)
{
return new JsonQuery<Account>()
{
FileLocation = "fileLocation",
Condition = acc => acc.Status == parameters.Status && acc.Balance > parameters.Balance
};
}
}
public class GetAccountsByStatusAndBalanceHigherThanQuery : IQuery<IEnumerable<Account>>
{
public string Status { get; set; }
public decimal Balance { get; set; }
}
public class GetAccountsByStatusAndBalanceHigherThanQueryHandler :
IQueryHandler<GetAccountsByStatusAndBalanceHigherThanQuery, IEnumerable<Account>>
{
private readonly IQueryBuilder<JsonQuery<Account>, GetAccountsByStatusAndBalanceHigherThanQueryParameters>
_queryBuilder;
private readonly IQueryHandler<JsonQuery<Account>, IEnumerable<Account>> _connection;
public GetAccountsByStatusAndBalanceHigherThanQueryHandler(
IQueryBuilder<JsonQuery<Account>, GetAccountsByStatusAndBalanceHigherThanQueryParameters> queryBuilder,
IQueryHandler<JsonQuery<Account>, IEnumerable<Account>> connection)
{
_queryBuilder = queryBuilder;
_connection = connection;
}
public IEnumerable<Account> Handle(GetAccountsByStatusAndBalanceHigherThanQuery query)
{
var jsonQuery = _queryBuilder.Build(new GetAccountsByStatusAndBalanceHigherThanQueryParameters
{
Status = query.Status,
Balance = query.Balance
});
return _connection.Handle(jsonQuery);
}
}
Итак, есть два соединения - одно соединение с базой данных и одно соединение с файлом Json.Я поместил настройки для соединений в запросы - и хотя для соединения с базой данных требуется строка соединения и команда SQL, для соединения Json требуется местоположение файла и некоторая фильтрация результатов.Проблема в последнем обработчике запросов - GetAccountsByStatusAndBalanceHigherThanQueryHandler.Мне нужно, чтобы это зависело от конкретного соединения, иначе я не смогу его скомпилировать.Я хочу убедиться, что я могу изменить соединение, просто изменив введенные параметры, и все будет работать правильно.
Не могли бы вы посоветовать, как сделать так, чтобы я мог легко изменить соединения, а такжеэта архитектура хороша вообще?