如何创建一个与SQL Server和SQLite兼容的DbCommand,不需要太大的条件

本文关键字:条件 DbCommand SQLite 不需要 Server 创建 何创建 一个 SQL | 更新日期: 2023-09-27 18:06:00

假设我有一个c#代码

private const string INSERT = "INSERT INTO Person VALUES (@FirstName, @LastName)";
public static DbCommand INSERTCOMMAND(IPerson person)
{
    DbCommand command = null;
    var sqlParams = new List<DbParameter>();
    if(SQLManagerFactory.SQLManager is SQLServerManager)
    {
        command = new SqlCommand(INSERT);
        sqlParams.Add(new SqlParameter("@FirstName", person.FirstName);
        sqlParams.Add(new SqlParameter("@LastName", person.LastName);
    }
    else // SQLiteManager
    {
        command = new SQLiteCommand(INSERT);
        sqlParams.Add(new SQLiteParameter("@FirstName", person.FirstName);
        sqlParams.Add(new SQLiteParameter("@LastName", person.LastName);
    }
    command.Parameters.AddRange(sqlParams.ToArray());
    return command;
}

工作得很好。当然,在我的产品代码中,它更大,有更多的位置,为不同的命令做类似的事情。

我的问题是,有没有办法使它更短?我不希望复制和粘贴那些除了调用不同的构造函数之外基本上做同样事情的代码。

非常感谢。

如何创建一个与SQL Server和SQLite兼容的DbCommand,不需要太大的条件

像这样就可以了,我省略了一些细节,但是你可以自己弄清楚:

private const string INSERT = "INSERT INTO Person VALUES (@FirstName, @LastName)";
public static DbCommand INSERTCOMMAND(IPerson person)
{
    DbCommand command = null;
    var sqlParams = new List<DbParameter>();
    MySqlEnum sqlType = SQLManagerFactory.SQLManager is SQLServerManager ? MySqlEnum.SQLServer : MySqlEnum.sqlLite
    if(sqlType == MySqlEnum.SQLServer)
        command = new SqlCommand(INSERT);
    else // SQLiteManager
        command = new SQLiteCommand(INSERT);
    sqlParams.Add(new CustomSqlParameter(sqlType ,"@FirstName", person.FirstName);
    sqlParams.Add(new CustomSqlParameter(sqlType ,"@LastName", person.LastName);
    command.Parameters.AddRange(sqlParams.ToArray());
    return command;
}

CustomSqlParameter的代码应该很明显

在设计和可测试性方面,我认为在你的例子中把事情结合起来是不对的。

假设只对一个数据库进行了更改,而您需要更改INSERT查询,这将导致问题,因为相同的查询用于其他数据库。

实际上,您可以创建PersonRepository抽象:

public interface IPersonRepository
{
    void Add(IPerson person)
}

并创建该接口的两个实现:

public SqlServerPersonRepository : IPersonRepository 
{
    void Add(IPerson person)
    {
        //sql server specific code
    }
}
public SqlLitePersonRepository : IPersonRepository 
{
    void Add(IPerson person)
    {
        //sqlite specific code
    }
}

将特定于数据库的知识移动到SQLManager类中(或者创建您自己的类来包装它):

public static DbCommand INSERTCOMMAND(IPerson person)
{
    var sqlParams = new List<DbParameter>();
    var sql = SQLManagerFactory.SQLManager; // or MyOwnSQLManager
    var command = sql.CreateCommand(INSERT);
    sqlParams.Add(sql.CreateParameter("@FirstName", person.FirstName));
    sqlParams.Add(sql.CreateParameter("@LastName", person.LastName));
    command.Parameters.AddRange(sqlParams.ToArray());
    return command;
}