У меня есть небольшая библиотека, в которой я выполняю 1 длительную операцию и, основываясь на этой операции, я сохраняю некоторые данные в таблицах базы данных. Теперь это небольшая библиотека, которая не включает в себя много операций с таблицами базы данных, поэтому я использовал Ado .net для управления уровнем доступа к данным.
Я создал базовый класс, куда поместил строку подключения и выполнение команд Ado.net.
У меня есть 3-4 класса с некоторыми методами, выполняющими вставку, обновление и удаление, но проблема в том, что мне приходится передавать строку подключения каждому из этих 4 классов всякий раз, когда я создаю объект этого класса.
Код:
internal abstract class BaseRepo
{
private readonly string connectionString;
protected int TestId;
protected int VariantId;
public BaseRepo() { }
protected BaseRepo(string connection)
{
this.connectionString = connection;
}
internal virtual void ExecuteQuery(string query,
IList<SqlParameter> parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(query, conn))
{
conn.Open();
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
command.ExecuteNonQuery();
}
}
}
internal virtual void ExecuteQueryWithTransaction(SqlConnection connection,SqlTransaction transaction, string query,
IList<SqlParameter> parameters)
{
using (SqlCommand command = new SqlCommand(query, connection, transaction))
{
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
command.ExecuteNonQuery();
}
}
internal virtual int ExecuteScalar(string query,
IList<SqlParameter> parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(query, conn))
{
conn.Open();
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
var data = command.ExecuteScalar();
if (data == null)
return 0;
return (int)data;
}
}
}
}
internal class VariantRepo : BaseRepo
{
public VariantRepo(string connectionString,int testId,int variantId) : base(connectionString)
{
TestId = testId;
VariantId = variantId;
}
public VariantRepo(testId) : base(connectionString)
{
TestId = testId;
}
public void DeleteVariantData()
{
string query = "";
List<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@TestId", TestId));
parameters.Add(new SqlParameter("@VariantId", VariantId));
ExecuteQuery(query, parameters);
}
}
internal class RegionRepo : BaseRepo
{
public RegionRepo(string connectionString, int variantId) : base(connectionString)
{
VariantId = variantId;
}
public int GetRegionIdByVariantId()
{
string query = "";
List<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@id", VariantId));
return ExecuteScalar(query, parameters);
}
}
Как вы видите, у меня есть 4 класса здесь, и от каждого из этого класса я должен передать строку подключения в базовый класс:
1) VariantRepo
2) RegionRepo
3) CategoryRepo
(не показано, но то же, что и выше 2)
4) TestRepo
(не показано, но аналогично вышеуказанному 2).
Итак, есть 2 вещи, которые я хотел бы рассмотреть здесь:
1) Можно спроектировать базовый класс таким образом, чтобы мне нужно было передавать строку подключения только один раз, а не для каждого из 4 конкретных классов?
2) Я хочу скрыть эту грязную логику (Sql parameter creation code
) за некоторым классом, чтобы иметь лучшую читаемость, потому что я должен делать это во многих местах:
List<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@TestId", TestId));
parameters.Add(new SqlParameter("@VariantId", VariantId));
Я подумал, что базовый класс должен быть конкретным классом, но чем иметь базовый класс в качестве абстрактного, имеет больше смысла, я думаю, именно поэтому я отметил базовый класс как абстрактный.
Может кто-нибудь помочь мне спроектировать это лучше?