【发布时间】:2019-06-30 06:02:34
【问题描述】:
我有一个包含超过 200,000 行代码的旧应用程序。
它目前使用 MS Sql Express 作为其数据存储。调用了存储过程,CURD 功能主要通过表适配器实现。
由于 SqlExpress 有 10 GB 的限制,我正在尝试将应用程序更改为使用 MySql 数据库。
我使用mysql workbench自带的迁移向导来导入所有数据。
现在是我面临的问题。
在当前代码中,有一个单例连接管理器是这样访问的
var connection = ConnectionManager.GetInstance().GetNewSQLConnection();
if (connection.State == ConnectionState.Closed) connection.Open();
int? iErrorNumber = 0;
DataTable dt;
string sErrorMessage = "";
try
{
SqlParameter[] paramsToStore = new SqlParameter[3];
paramsToStore[0] = new SqlParameter("@iErrorNumber", SqlDbType.Int);
paramsToStore[0].Value = iErrorNumber;
paramsToStore[1] = new SqlParameter("@sErrorMessage", SqlDbType.NVarChar);
paramsToStore[1].Size = 8000;
paramsToStore[1].Value = sErrorMessage;
paramsToStore[2] = new SqlParameter("@iAssayPK", iAssayPK);
dt = SqlHelper.ExecuteDataset(connection, CommandType.StoredProcedure, "USP_ASY_AssayUseCount", paramsToStore).Tables[0];
}
这是 ConnectionManager 的提取接口
public interface IConnectionManager
{
string GenerateDBUsername(string _sDatabase, string _sUsername);
Connection GetConnection();
Connection GetCurrentConnection();
SqlConnection GetNewSQLConnection();
string GetOrmConnectionString();
void SetCurrentConnection(Connection _oConCurrentConnection);
void UpdateConnection(Connection _oTheConnection, bool _bSavePassword, string _sNameBeforeUpdate, string ServerAddress);
}
如您所见,GetNewSQLConnection() 返回一个 SqlConnection 对象。 有数百个地方使用了这种连接。 并且大多数时候它都像这样传递给 tableAdapter
using (CustomNamesTableAdapter tadaCustomNames = new CustomNamesTableAdapter())
{
try
{
tadaCustomNames.Connection = ConnectionManager.GetInstance().GetNewSQLConnection();
tadaCustomNames.Fill(_dtblToFill, ref iErrorNumber, ref sErrorMessage);
if (iErrorNumber != 0)
{
ErrorLogManager.GetInstance().WriteDBError(DateTime.Now, (int)iErrorNumber, sErrorMessage, "USP_CSN_GetCustomNames", this.GetType().ToString(), "void GetCustomerNames(CommonDataSet.CustomNamesDataTable _dtblToFill)", "Error while executing SP");
throw new BDRException(Globals.BDRMessageType.EXCEPTION, DateTime.Now, 46, "Error while executing SP");
}
}
我想如果我可以继承 SqlConnection 类,我就可以创建一个类,也许我可以尝试将 SqlConnection 和 MySqlConneciton 组合成一个对象,并根据所选的当前数据库使用基础对象。
但我正在查看的表适配器也使用 System.Data.SqlClient 中的其他类型,例如参数,并且尝试更新所有代码将意味着更改代码很多地方....
我知道如果应用程序是使用 ORM 构建的,这将是非常不同的,但因为它不是......我正在寻找有关如何解决这个问题的建议。
如果我能以某种方式使用接口并使用不同的实现(使用不同的数据库),那应该是可行的方法,但由于所有代码都已经依赖于类型化的(SqlConnection、Sql.Data.SqlClient.SqlCommand 等)参数,我没有办法避免这种情况..
其他选择是购买 Sql Standard,它比 Express Edition 贵得多。或尝试归档未积极使用的旧数据并将数据库大小保持在限制以下,或者可能创建多个“数据”数据库(应用程序工作的数据)并将其中一个用于应用程序数据(用户/角色/等)
这里只是一个想法,如果这个应用程序是用 python 编写的……改变这种类型会更容易吗?
【问题讨论】:
-
恐怕如果你的代码库深深依赖于那个命名空间,这将是一次重大的重新设计。您可能应该考虑首先切换到从具体数据库中更好地抽象的设计,然后在第二步中更改为 MySQL。
-
是的,如果必须继续进行重构,则必须构建抽象层以避免未来的痛苦。
-
ADO.NET 类实现接口abstract classes and class factories。从一个提供程序切换到另一个提供程序就像更改 app.config 中的设置一样简单,只要应用程序使用
DbConnection、DbCommand等。这在 Python 中没有什么不同。如果您使用特定于提供程序的类,您将无法迁移 -
顺便说一句,该代码很糟糕 - 看起来它试图通过使用单例连接而不是默认连接池来模拟类工厂而没有任何好处甚至损害性能。我敢打赌,为了防止这些全局连接和事务相互阻塞,会有很多麻烦。我会更关心 MySQL 将如何对此做出反应
-
鉴于代码状态不佳,我建议首先使用 SQL Server Express 2017 并选择压缩,按年份对数据进行分区并将旧数据移出。与尝试使用如此脆弱的代码迁移到另一个数据库相比,风险要小得多。这可能会完全缓解这个问题。在任何情况下,它都会为您赢得至少清理数据访问代码的时间,或者迁移到 ADO.NET 的类工厂模型,或者引入像 EF Core/NH 这样的真正 ORM 或像 Dapper 这样的 microORM。
GetOrmConnectionString()非常可疑 - 有人尝试构建自定义 ORM 吗?
标签: c# mysql sql-server