Как правильно организовать класс по работе с БД - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте. У меня есть проект каталогизатора. Изначально писал основываясь на MSSQL CE. Потом захотел добавить возможность использования MSSQL Server. И начал сочинять)) Написал фабрику возвращающую класс по работе с конкретной СУБД
public static class DbProviderFactory
{
     public static DatabaseProvider GetProvider(DBType dbType, string ConnectStr)
     {
         DatabaseProvider provider = null;
        switch (dbType)
         {
             case DBType.MSSQL:
                 provider = new SqlDbProvider(ConnectStr);
                 break;
             case DBType.MSSQLCE:
                 provider = new SqlCeDbProvider(ConnectStr);
                 break;
             default:
                 throw new ArgumentException("Wrong database type!");
         }
         return provider;
     }
}
где DBType - перечисление с вариантами СУБД
public enum DBType
{
    None,
    MSSQL,
    MSSQLCE
}
Написал абстрактный класс по работе с СУБД где перечислил абстрактные классы по работе с таблицами в БД
public abstract class DatabaseProvider
{
    protected string CONNECT_STR = string.Empty;
    protected IDbConnection CNN = null;
 
    public DatabaseProvider(string connectStr)
    {
        CONNECT_STR = connectStr;
    }
 
    public abstract ProjectTableAbstract GetProjectTable();
 
    public abstract FirstUsageTableAbstract GetFirstUsageTable();
 
    public abstract OboznachenieTableAbstract GetOboznachenieTable();
 
    public abstract LiteralTableAbstract GetLiteralTable();
 
    public abstract IspolniteliTableAbstract GetIspolniteliTable();
 
    public abstract InventarNumberTableAbstract GetInventarNumberTable();
}
От него унаследовал класс работы с конкретной СУБД.
public class SqlCeDbProvider : DatabaseProvider // Для MSSQL CE
{
    public SqlCeDbProvider(string connectStr)
        : base(connectStr)
    {
        CNN = new SqlCeConnection(CONNECT_STR);
    }
 
    public override ProjectTableAbstract GetProjectTable()
    {
        return new ProjectTableSqlCe(CNN);
    }
 
    public override FirstUsageTableAbstract GetFirstUsageTable()
    {
        return new FirstUsageTableSqlCe(CNN);
    }
 
    public override OboznachenieTableAbstract GetOboznachenieTable()
    {
        return new OboznachenieTableSqlCe(CNN);
    }
 
    public override LiteralTableAbstract GetLiteralTable()
    {
        return new LiteralTableSqlCe(CNN);
    }
 
    public override IspolniteliTableAbstract GetIspolniteliTable()
    {
        return new IspolniteliTableSqlCe(CNN);
    }
 
    public override InventarNumberTableAbstract GetInventarNumberTable()
    {
        return new InventarNumberTableSqlCe(CNN);
    }
}
 
class SqlDbProvider : DatabaseProvider // Для MSSQL Server
{
    public SqlDbProvider(string connectStr)
        : base(connectStr)
    {
        CNN = new SqlConnection(CONNECT_STR);
    }
 
    public override OboznachenieTableAbstract GetOboznachenieTable()
    {
        throw new NotImplementedException();
    }
 
    public override FirstUsageTableAbstract GetFirstUsageTable()
    {
        throw new NotImplementedException();
    }
 
    public override ProjectTableAbstract GetProjectTable()
    {
        throw new NotImplementedException();
    }
 
    public override LiteralTableAbstract GetLiteralTable()
    {
        throw new NotImplementedException();
    }
 
    public override IspolniteliTableAbstract GetIspolniteliTable()
    {
        throw new NotImplementedException();
    }
 
    public override InventarNumberTableAbstract GetInventarNumberTable()
    {
        throw new NotImplementedException();
    }
}
Написал набор абстрактных классов по работе с таблицами (на примере ProjectTable)
public abstract class ProjectTableAbstract
{
    protected IDbConnection CNN = null;
 
    public ProjectTableAbstract(IDbConnection Connection)
    {
        CNN = Connection;
    }
 
    public abstract List<Project> GetEntities();
 
    public abstract bool AddToDB(string value);
 
    public abstract bool DeleteFromDB(string value, int id);
 
    public abstract bool RenameInDB(string oldValue, string newValue, int oldValueId);
}
Написал набор конкретных классов по работе с таблицами (на примере ProjectTable)
class ProjectTableSqlCe : ProjectTableAbstract
{
    static SqlCeConnection SQLCeCon;
    
    public ProjectTableSqlCe(IDbConnection Connection) : base(Connection)
    {
        SQLCeCon = (SqlCeConnection)CNN;
    }
 
    public override List<Project> GetEntities()
    {
        List<Project> _lst = new List<Project>();
        if (SQLCeCon.State == ConnectionState.Closed)
        {
            SQLCeCon.Open();
        }
        _lst.Clear();
        SqlCeCommand ceCmd;
        SqlCeDataReader ceDR;
        ceCmd = new SqlCeCommand("", (SqlCeConnection)CNN);
        ceDR = ceCmd.ExecuteReader();
        while (ceDR.Read())
        {
            _lst.Add(new Project((int)ceDR[0], (string)ceDR[1]));
        }
        ceDR.Close();
        CNN.Close();
        return _lst;
    }
 
    public override bool AddToDB(string value)
    {
        int i = -1;
        string cmd = "";
        SqlCeCommand _cmd = new SqlCeCommand();
        _cmd = new SqlCeCommand(cmd, SQLCeCon);
        _cmd.Parameters.Add("@prj_name", SqlDbType.NVarChar).Value = value;
        i = SQLExec(_cmd);
        GetEntities();
        return i > 0;
    }
 
    public override bool DeleteFromDB(string value, int id)
    {
        string cmd = "";
        int i = -1;
        SqlCeCommand _cmd = new SqlCeCommand();
        _cmd = new SqlCeCommand(cmd, SQLCeCon);
        _cmd.Parameters.Add("@id", SqlDbType.Int).Value = id;
        try
        {
            i = SQLExec(_cmd);
        }
        catch (Exception ex)
        {
            if (ex is SqlCeException)
            {
                ExceptionHandler.SQLEntityException exc =
                new ExceptionHandler.SQLEntityException();
                throw exc;
            }
            else
            { throw ex; }
        }
        return i > 0;
    }
 
    public override bool RenameInDB(string oldValue, string newValue, int oldValueId)
    {
        string cmd = "";
        int i = -1;
        SqlCeCommand _cmd = new SqlCeCommand();
        _cmd = new SqlCeCommand(cmd, SQLCeCon);
        _cmd.Parameters.Add("@id", SqlDbType.Int).Value = oldValueId;
        _cmd.Parameters.Add("@name", SqlDbType.NVarChar).Value = newValue;
        try
        {
            i = SQLExec(_cmd);
        }
        catch (Exception ex)
        {
            if (ex is SqlCeException)
            {
                ExceptionHandler.SQLEntityException exc =
                new ExceptionHandler.SQLEntityException();
                throw exc;
            }
            else
            { throw ex; }
        }
        GetEntities();
        return i > 0;
    }
 
    protected int SQLExec(SqlCeCommand SQLCommand)
    {
        int i = -1;
        if (CNN.State == ConnectionState.Closed)
        {
            CNN.Open();
        }
        try
        {
            i = SQLCommand.ExecuteNonQuery();
        }
        finally
        {
            CNN.Close();
        }
        return i;
    }
}
Мне бы хотелось вынести метод SQLExec из каждого конкретного класса вынсти в некий класс (возможно абстактный)? Посмотрев диаграмму классов на все это "творчества", у меня возник вопрос, а не должены ли абстрактные классы наледоваться от какого-то общего класса куда можно было бы вынести общие методы как, например SQLExec? Прошу дать оценку моему певому опыту работы с фабрикой.

Решение задачи: «Как правильно организовать класс по работе с БД»

textual
Листинг программы
  public abstract class ProjectTableAbstract
  {
    private readonly string _connectionString;
 
    protected ProjectTableAbstract(string connectionString)
    {
      _connectionString = connectionString;
    }
 
    public virtual List<Project> GetEntities()
    {
      return Query<List<Project>>("Your query");
    }
 
    public virtual bool AddToDb(string value)
    {
      return SqlExecuteNonQuery("Your query") > -1;
    }
 
    public virtual bool DeleteFromDb(string value, int id)
    {
      return SqlExecuteNonQuery("Your query") > -1;
    }
 
    public virtual bool RenameInDb(string oldValue, string newValue, int oldValueId)
    {
      return SqlExecuteNonQuery("Your query") > -1;
    }
 
    protected abstract IDbConnection GetConnection(string str);
    protected abstract IDbCommand GetCommand(IDbConnection connection, string query);
 
    protected virtual int SqlExecuteNonQuery(string query)
    {
      using (var connection = GetConnection(_connectionString))
      {
        connection.Open();
        using (var command = GetCommand(connection,query))
        {
          return command.ExecuteNonQuery();
        }
      }
    }
 
    protected virtual T Query<T>(string query)
    {
      using (var connection = GetConnection(_connectionString))
      {
        connection.Open();
        using (var command = GetCommand(connection, query))
        {
          //парсинг результата запроса и запись в модель
          return default(T);
        }
      }
    }
  }
 
  public class ProjectTableSqlCe : ProjectTableAbstract
  {
    public ProjectTableSqlCe(string connectionString) : base(connectionString)
    {
    }
 
    protected override IDbConnection GetConnection(string str)
    {
      throw new NotImplementedException();
    }
 
    protected override IDbCommand GetCommand(IDbConnection connection, string query)
    {
      throw new NotImplementedException();
    }
  }
 
  public class ProjectTableMsSql:ProjectTableAbstract
  {
    public ProjectTableMsSql(string connectionString) : base(connectionString)
    {
    }
 
    protected override IDbConnection GetConnection(string str)
    {
      throw new NotImplementedException();
    }
 
    protected override IDbCommand GetCommand(IDbConnection connection, string query)
    {
      throw new NotImplementedException();
    }
  }
 
  public static class TableFactory
  {
    public static ProjectTableAbstract GetTable(string name,string connectionString)
    {
      throw new NotImplementedException();
    }
  }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

8   голосов , оценка 4.25 из 5
Похожие ответы