SQL和SQLite的包装器

时间:2014-02-05 19:25:21

标签: c# sql sqlite

我正在尝试扩展最初使用sqlite数据库设计的应用程序,以便与sql server进行交互。我最初的想法是创建一个包装类来处理这些事务。使用Sqlselect函数返回数据,使用SQLexecute函数执行非查询事务。

我最初的刺伤是这样的:

public static class Sqlwrapper
{

    public static int Sqltype = 0;

    /// <summary>
    /// Fills a datatable with the result of the select command.
    /// </summary>
    /// <param name="cmdstring"> Connection string </param>
    /// <param name="dt">Datatable to be filled</param>
    /// <returns>Returns true if successful, false if there is any issues.</returns>
    public static bool Sqlselect(string cmdstring, out DataTable dt)
    {
        dt = new DataTable();

        if (Sqltype == 0)
        {
            SQLiteConnection c = new SQLiteConnection("Data Source=Resources\\DB.sqlite;Version=3");
            try
            {
                c.Open();
                SQLiteDataAdapter a = new SQLiteDataAdapter(cmdstring, c);
                a.Fill(dt);
                c.Close();
                return true;
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc.Message);
                c.Close();
                return false;
            }
        }
        else
        {
            SqlConnection c = new SqlConnection("Server=Server;Database=DB;Trusted_Connection=True;");
            try
            {
                c.Open();
                SqlDataAdapter a = new SqlDataAdapter(cmdstring, c);
                a.Fill(dt);
                c.Close();
                return true;
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc.Message);
                c.Close();
                return false;
            }
        }
    }

    /// <summary>
    /// Executes a sql command
    /// </summary>
    /// <param name="cmdstring">sql command string</param>
    /// <returns>True for success.</returns>
    public static bool Sqlexecute(string cmdstring)
    {
        if (Sqltype == 0)
        {
            SQLiteConnection c = new SQLiteConnection("Data Source=Resources\\DB.sqlite;Version=3");
            try
            {
                c.Open();
                SQLiteCommand cmd = new SQLiteCommand(cmdstring, c);
                cmd.ExecuteNonQuery();
                c.Close();
                return true;
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc.Message);
                c.Close();
                return false;
            }
        }
        else
        {
            SqlConnection c = new SqlConnection("Server=Server;Database=DB;Trusted_Connection=True;");
            try
            {
                c.Open();
                SqlCommand cmd = new SqlCommand(cmdstring, c);
                cmd.ExecuteNonQuery();
                c.Close();
                return true;
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc.Message);
                c.Close();
                return false;
            }
        }
    }

}

这似乎有效,但是我遇到了一些问题,例如。从sqlserver中提取我需要添加一个用户名,对于我们不发送该数据的本地数据库。

我传递命令字符串和/或获取数据表的方法是一个好习惯吗?有一种我更容易忽视的方法吗?

谢谢!

编辑: 这是第二个实现:

public class DbManager
{
    public IDbProvider DbProvider;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sqltype">An integer to set which database type to use, defaults to 0 for sqlite, set to 1 for sql server.</param>
    public DbManager(int sqltype = 0)
    {
        if (sqltype == 0)
        {
            DbProvider = new SqliteWrapper();
        }
        else
        {
            DbProvider = new SqlWrapper();
        }
    }
}

public interface IDbProvider
{
    /// <summary>
    /// Fills a datatable with the result of the select command.
    /// </summary>
    /// <param name="cmdstring"> Connection string </param>
    /// <param name="dt">Datatable to be filled</param>
    /// <returns>Returns true if successful, false if there is any issues.</returns>
    bool Sqlselect(string cmdstring, out DataTable dt);

    /// <summary>
    /// Executes a sql command
    /// </summary>
    /// <param name="cmdstring">sql command string</param>
    /// <returns>True for success.</returns>
    bool Sqlexecute(string cmdstring);
}

public class SqliteWrapper : IDbProvider
{
    /// <summary>
    /// Fills a datatable with the result of the select command.
    /// </summary>
    /// <param name="cmdstring"> Connection string </param>
    /// <param name="dt">Datatable to be filled</param>
    /// <returns>Returns true if successful, false if there is any issues.</returns>
    public bool Sqlselect(string cmdstring, out DataTable dt)
    {
        dt = new DataTable();
        SQLiteConnection c = new SQLiteConnection("Data Source=Resources\\DB.sqlite;Version=3");
        try
        {
            c.Open();
            SQLiteDataAdapter a = new SQLiteDataAdapter(cmdstring, c);
            a.Fill(dt);
            c.Close();
            return true;
        }
        catch (Exception exc)
        {
            Debug.WriteLine(exc.Message);
            c.Close();
            return false;
        }
    }

    /// <summary>
    /// Executes a sql command
    /// </summary>
    /// <param name="cmdstring">sql command string</param>
    /// <returns>True for success.</returns>
    public bool Sqlexecute(string cmdstring)
    {
        SQLiteConnection c = new SQLiteConnection("Data Source=Resources\\DB.sqlite;Version=3");
        try
        {
            c.Open();
            SQLiteCommand cmd = new SQLiteCommand(cmdstring, c);
            cmd.ExecuteNonQuery();
            c.Close();
            return true;
        }
        catch (Exception exc)
        {
            Debug.WriteLine(exc.Message);
            c.Close();
            return false;
        }
    }
}

public class SqlWrapper : IDbProvider
{
    /// <summary>
    /// Fills a datatable with the result of the select command.
    /// </summary>
    /// <param name="cmdstring"> Connection string </param>
    /// <param name="dt">Datatable to be filled</param>
    /// <returns>Returns true if successful, false if there is any issues.</returns>
    public bool Sqlselect(string cmdstring, out DataTable dt)
    {
        dt = new DataTable();

        SqlConnection c = new SqlConnection("Server=Server;Database=DB;Trusted_Connection=True;");
        try
        {
            c.Open();
            SqlDataAdapter a = new SqlDataAdapter(cmdstring, c);
            a.Fill(dt);
            c.Close();
            return true;
        }
        catch (Exception exc)
        {
            Debug.WriteLine(exc.Message);
            c.Close();
            return false;
        }

    }
    public bool Sqlexecute(string cmdstring)
    {


        SqlConnection c = new SqlConnection("Server=Server;Database=DB;Trusted_Connection=True;");
        try
        {
            c.Open();
            SqlCommand cmd = new SqlCommand(cmdstring, c);
            cmd.ExecuteNonQuery();
            c.Close();
            return true;
        }
        catch (Exception exc)
        {
            Debug.WriteLine(exc.Message);
            c.Close();
            return false;
        }

    }
}

2 个答案:

答案 0 :(得分:1)

通常,ADO.NET框架中的每个类都有一个由所有提供程序使用的公共父级。因此,您应该能够通过使用工厂模式(http://www.dofactory.com/Patterns/PatternFactory.aspx)或抽象工厂(http://www.dofactory.com/Patterns/PatternAbstract.aspx)来解决应用程序使用两种数据库这一事实。

这可以确保您不需要两个包装器的实现。例如:

public abstract class SqlFactory
{
    public abstract DbConnection CreateConnection();

    public abstract DataAdapter CreateAdapter(string command, DbConnection connection);

}

public class SqlLiteFactory : SqlFactory
{
    public override DbConnection CreateConnection()
    {
        return new SQLiteConnection("Data Source=Resources\\DB.sqlite;Version=3");
    }

    public override DataAdapter CreateAdapter(string command, DbConnection connection)
    {
        return new SQLiteDataAdapter(command, connection as SQLiteConnection);
    }
}

public class MSSqlFactory : SqlFactory
{
    public override DbConnection CreateConnection()
    {
        return new SqlConnection("CONNECTION STRING HERE");
    }

    public override DataAdapter CreateAdapter(string command, DbConnection connection)
    {
        return new SqlDataAdapter(command, connection as SqlConnection);
    }
}

//Composite and Singleton class...
public class SqlHandler : SqlFactory
{
    private static SqlHandler _instance;

    private SqlLiteFactory _sqlLiteFactory;
    private MSSqlFactory _msSqlFactory;

    //Singleton pattern.
    public static SqlHandler Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new SqlHandler();
            }

            return _instance;
        }
    }

    private SqlHandler()
    {
        _sqlLiteFactory = new SqlLiteFactory();
        _msSqlFactory = new MSSqlFactory();
    }

    public override DbConnection CreateConnection()
    {
        //Some code determining if better to use SqlLite or MS SQL.
        if (useSqlLite)
        {
            return _sqlLiteFactory.CreateConnection();
        }
        else
        {
            return _msSqlFactory.CreateConnection();
        }
    }

    public override DataAdapter CreateAdapter(string command, DbConnection connection)
    {
        //Some code determining if better to use SqlLite or MS SQL.
        if (useSqlLite)
        {
            return _sqlLiteFactory.CreateAdapter(command, connection);
        }
        else
        {
            return _msSqlFactory.CreateAdapter(command, connection);
        }
    }
}

因此,当您需要调用包装器中相关的任何数据库时,您可以执行以下操作:

DbConnection c = SqlHandler.Instance.CreateConnection();

这种方式还允许您轻松实现新数据库。

PS:对于你的连接字符串,我建议你使用App.config文件来设置它。如果将来发生任何变化,您将能够更改数据库而无需重新编译应用程序。

答案 1 :(得分:0)

为什么不创建Database Provider的接口并为每种类型创建两个类。您可以在上面创建一个DB Manager类,它可以同时调用该对象或只调用一个