C# 在C中使用相同的方法访问不同的SQL Server类型,如TSql或MySql#
目前,我正在编写一个程序来访问多种“类型”的SQL服务器,例如C#中的TSQL或MySQL。我创建了一个基类C# 在C中使用相同的方法访问不同的SQL Server类型,如TSql或MySql#,c#,mysql,tsql,inheritance,dry,C#,Mysql,Tsql,Inheritance,Dry,目前,我正在编写一个程序来访问多种“类型”的SQL服务器,例如C#中的TSQL或MySQL。我创建了一个基类DBConnector,它有一个抽象方法: public abstract class DBConnector { //some other code... protected abstract int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int
DBConnector
,它有一个抽象方法:
public abstract class DBConnector
{
//some other code...
protected abstract int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20);
//some other code...
}
现在我有两个派生类TSqlConnector
和MySqlConnector
,它们实现了这个抽象方法:
public abstract class DBConnector
{
//some other code...
protected abstract int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20);
//some other code...
}
对于MySql,它看起来是这样的:
protected override int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20)
{
int result = -1;
using (MySqlCommand cmd = new MySqlCommand(statement, (MySqlConnection)con))
{
cmd.CommandTimeout = timeout;
cmd.Connection.Open();
if (executeAsScalar)
{
object resultObject = cmd.ExecuteScalar();
if (resultObject is int tmpResult)
result = tmpResult;
}
else
{
result = cmd.ExecuteNonQuery();
}
}
return result;
}
protected override int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20)
{
int result = -1;
using (SqlCommand cmd = new SqlCommand(statement, (SqlConnection)con))
{
cmd.CommandTimeout = timeout;
cmd.Connection.Open();
if (executeAsScalar)
{
object resultObject = cmd.ExecuteScalar();
if (resultObject is int tmpResult)
result = tmpResult;
}
else
{
result = cmd.ExecuteNonQuery();
}
}
return result;
}
对于TSql,它看起来是这样的:
protected override int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20)
{
int result = -1;
using (MySqlCommand cmd = new MySqlCommand(statement, (MySqlConnection)con))
{
cmd.CommandTimeout = timeout;
cmd.Connection.Open();
if (executeAsScalar)
{
object resultObject = cmd.ExecuteScalar();
if (resultObject is int tmpResult)
result = tmpResult;
}
else
{
result = cmd.ExecuteNonQuery();
}
}
return result;
}
protected override int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20)
{
int result = -1;
using (SqlCommand cmd = new SqlCommand(statement, (SqlConnection)con))
{
cmd.CommandTimeout = timeout;
cmd.Connection.Open();
if (executeAsScalar)
{
object resultObject = cmd.ExecuteScalar();
if (resultObject is int tmpResult)
result = tmpResult;
}
else
{
result = cmd.ExecuteNonQuery();
}
}
return result;
}
顺便说一下,这些方法还包含一些错误处理和其他内容,但是我简化了我在这篇文章中的方法
在我的其他自定义方法中调用此方法,如下所示:
调用Insert方法中的代码(obj
是一个模型类的实例,该模型类具有与数据库表相同的属性,包括ID):
我的调用更新方法中的代码:
affectedLines = ExecuteNonQueryOrScalar(GetConnection(), sql, false); //false for nonQuery-execution
affectedLines = ExecuteNonQueryOrScalar(GetConnection(), sql, false); //false for nonQuery-execution
我的调用删除方法中的代码:
affectedLines = ExecuteNonQueryOrScalar(GetConnection(), sql, false); //false for nonQuery-execution
affectedLines = ExecuteNonQueryOrScalar(GetConnection(), sql, false); //false for nonQuery-execution
GetConnection()
返回运行时为SqlConnection
或MySqlConnection
的DbConnection
对象<代码>sql是我的sql字符串。布尔参数决定是在ExecuteNonQueryOrScalar()
中调用ExecuteNonQuery
还是调用ExecuteScalar
现在回答我的问题:
protected override int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20)
{
int result = -1;
using (MySqlCommand cmd = new MySqlCommand(statement, (MySqlConnection)con))
{
cmd.CommandTimeout = timeout;
cmd.Connection.Open();
if (executeAsScalar)
{
object resultObject = cmd.ExecuteScalar();
if (resultObject is int tmpResult)
result = tmpResult;
}
else
{
result = cmd.ExecuteNonQuery();
}
}
return result;
}
protected override int ExecuteNonQueryOrScalar(DbConnection con, string statement, bool executeAsScalar, int timeout = 20)
{
int result = -1;
using (SqlCommand cmd = new SqlCommand(statement, (SqlConnection)con))
{
cmd.CommandTimeout = timeout;
cmd.Connection.Open();
if (executeAsScalar)
{
object resultObject = cmd.ExecuteScalar();
if (resultObject is int tmpResult)
result = tmpResult;
}
else
{
result = cmd.ExecuteNonQuery();
}
}
return result;
}
DBConnector
中将这两个方法移到一个方法中,并使用泛型参数,我用其中T:IDBEntity
和其中K:DBConnection
限制了泛型参数,但这样做时会出现编译时错误。我真的找不到一个解决办法来防止这种情况
在阅读了回复后,我意识到如何改进代码。我将我的方法
ExecuteNonQueryOrScalar
移动到我的基类DBConnector
中,并添加了一个IDbCommand参数,该参数可以是运行时的任何IDbCommand对象。此方法如下所示(简化版):
下面是一个示例,我如何在同一DBConnector
-类中的Update
-方法(简化)中调用该ExecuteOnQueryOrScalar
-方法:
protected int Update<T, K>(T obj, List<DBCondition> filterValues = null) where T : IDBEntity, new() where K : IDbCommand, new()
{
int affectedLines = -1;
if (obj != null)
{
using (IDbCommand cmd = new K())
{
cmd.Connection = GetConnection();
cmd.CommandText = obj.GetSqlUpdateStatement(DBMapping.GetDBMapping<T>(), _sqlSpecificSymbols, filterValues);
affectedLines = ExecuteNonQueryOrScalar(cmd, false);
}
}
return affectedLines;
}
TSqlConnector:
public override int Update<T>(T obj, List<DBCondition> filterValues = null)
{
return base.Update<T, MySqlCommand>(obj, filterValues); //Call DbConnector.Update<T, K>() from the example above
}
public override int Update<T>(T obj, List<DBCondition> filterValues = null)
{
return base.Update<T, SqlCommand>(obj, filterValues); //Call DbConnector.Update<T, K>() from the example above
}
public override int Update(T obj,List filterValues=null)
{
返回base.Update(obj,filterValues);//从上面的示例中调用DbConnector.Update()
}
如果你想看更多我的代码,请尽管问我!如果你们中的一些人想了解我所做的一切,我还可以将我未简化的原始代码上传到github等网站。你的想法很好。但是.net团队中的某个人通过这种方式创建该工作为您节省了一些时间,如和 然后,您可以在需要时使用此接口的不同具体实现。例如,MySQL的
IDBConnection con=new-MySqlConnection
,SQL Server的IDBConnection con=new-SqlConnection
这些接口公开了常见的方法,如ExecuteNonQuery
。因此,您在代码中使用的只是一组接口。您的代码总是传递IDBConnection
s和IDBCommand
s,您只需在构建时选择所需的实现。这是
当然,在填充命令的实际文本时,必须使用正确的SQL方言
这和你想做的一样吗?听起来你想重新发明EntityFramework。你需要这方面的帮助吗?据我所知,唯一需要改变的代码是
SqlCommand cmd=new-SqlCommand(statement,(SqlConnection)con)
->命令的创建。@Neil我非常了解EF或Dapper等框架。但我只是想学习如何在没有任何外部框架的情况下以默认方式实现这一点,但使用SqlCommand、SqlConnection、DataReader等。这也帮助我更好地理解其他模式和设计可能性,例如DRY和多态性。非常感谢,这真的帮助了我!我编辑了我的帖子,并在其中添加了我的新代码。随便看看吧!