到目前为止,我的程序只针对任何类型的数据工作处理 Sql Server 。我希望我的程序也可以使用 MySql 。现在我做了这个改变,我想尽可能避免代码重复。所以我开始考虑使用两个具体工厂SqlServerFactory
和MySqlFactory
的工厂模式。这会奏效!但是我的许多数据库方法具有几乎相同的结构,除了在一个中,我们使用SqlConnection
和SqlCommand
,另一个我们使用MySqlConnection
和方法的其余部分代码基本相同。下面是我的一个SELECT方法的示例:
public DataTable GetSpyList()
{
DataTable dt = new DataTable();
using (OleDbConnection conn = new OleDbConnection(cs))
{
try
{
string query = "SELECT * FROM SpyList";
OleDbDataAdapter da = new OleDbDataAdapter(query, conn);
conn.Open();
da.Fill(dt);
conn.Close();
return dt;
}
catch (Exception ex)
{
return null;
}
}
}
如何通过使上述方法适用于任何类型的数据提供程序来减少代码重复?这可以通过使用DbProviderFactories来实现吗?
答案 0 :(得分:1)
是的,静态DbProviderFactories和DbProviderFactory类适合您的目的。
当然,这样的每个抽象都基于基类DbConnection,DbCommand,DbDataReader,DbDataAdapter的通用功能。
例如。在MySqlDataReader
类中,您可以找到方法GetString
的重载,该方法将要检索的列的名称作为输入。此重载不存在于SqlDataReader
中,您需要使用列的序号位置来检索数据。因此,在DbProviderFactory
的情况下,您只能在MySql提供程序和Sql Server提供程序之间使用通用版本的GetString(IE使用采用序数位置的GetString方法)。幸运的是,Intellisense可以帮助避免这个错误。
您可以将代码重写为
public DataTable GetSpyList()
{
DbProviderFactory fac = DbProviderFactories.GetFactory("MySQL.Data.MySqlClient");
DataTable dt = new DataTable();
using(DbConnection conn = fac.CreateConnection())
{
cn.ConnectionString = cs
DbDataAdapter da = fac.CreateDataAdapter();
da.SelectCommand = conn.CreateCommand();
da.SelectCommand.CommandText = "SELECT * FROM SpyList";
try
{
conn.Open();
da.Fill(dt);
return dt;
}
catch (Exception ex)
{
return null;
}
}
}
此示例使用数据提供程序的固定名称,但当然,您可以从某种配置文件中读取此名称,并让程序更改其基础数据库,从而更改配置文件中的条目。