C# 继承问题-从Access数据库文件和SQL Express检索数据

C# 继承问题-从Access数据库文件和SQL Express检索数据,c#,database,ms-access,inheritance,sql-server-express,C#,Database,Ms Access,Inheritance,Sql Server Express,我正在开发一个应用程序,它将在一开始连接到Access数据库,计划在不久的将来切换到MS SQL或SQL Express。datatables结构对于这两种类型的数据库都是相同的,我试图避免重复代码,并试图找到最小化代码的方法 例如,我编写了以下函数,用于从Access数据库检索数据: public static DataTable GetActiveCalls() { string select = "SELECT call_id, call_time, msisdn,

我正在开发一个应用程序,它将在一开始连接到Access数据库,计划在不久的将来切换到MS SQL或SQL Express。datatables结构对于这两种类型的数据库都是相同的,我试图避免重复代码,并试图找到最小化代码的方法

例如,我编写了以下函数,用于从Access数据库检索数据:

public static DataTable GetActiveCalls()
    {
        string select = "SELECT call_id, call_time, msisdn, status FROM call WHERE status = 0 OR status = 1 ORDER by call_id ASC";
        OleDbCommand cmd = new OleDbCommand(select, conn);
        DataTable dt = new DataTable("Active Calls");
        OleDbDataAdapter DA = new OleDbDataAdapter(cmd);
        try
        {
            conn.Open();
            DA.Fill(dt);
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
        return dt;
    }
public static DataTable GetActiveCalls()
    {
        string select = "SELECT call_id, call_time, msisdn, status FROM call WHERE status = 0 OR status = 1 ORDER by call_id ASC";
        SqlCommand cmd = new SqlCommand(select, conn);
        DataTable dt = new DataTable("Active Calls");
        SqlDataAdapter DA = new SqlDataAdapter(cmd);
        try
        {
            conn.Open();
            DA.Fill(dt);
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
        return dt;
    }
以下代码适用于SQL Express数据库:

public static DataTable GetActiveCalls()
    {
        string select = "SELECT call_id, call_time, msisdn, status FROM call WHERE status = 0 OR status = 1 ORDER by call_id ASC";
        OleDbCommand cmd = new OleDbCommand(select, conn);
        DataTable dt = new DataTable("Active Calls");
        OleDbDataAdapter DA = new OleDbDataAdapter(cmd);
        try
        {
            conn.Open();
            DA.Fill(dt);
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
        return dt;
    }
public static DataTable GetActiveCalls()
    {
        string select = "SELECT call_id, call_time, msisdn, status FROM call WHERE status = 0 OR status = 1 ORDER by call_id ASC";
        SqlCommand cmd = new SqlCommand(select, conn);
        DataTable dt = new DataTable("Active Calls");
        SqlDataAdapter DA = new SqlDataAdapter(cmd);
        try
        {
            conn.Open();
            DA.Fill(dt);
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
        return dt;
    }
这两种方法几乎相同。唯一的区别是SqlCommand/OleDbCommand和SqlDataAdapter/OleDbDataAdapter。 还有一些方法以参数为例:

public static void AddMessage(string callID, string content)
    {
        string select =
            "INSERT INTO message(key, direction, content, read, write_time) VALUES (@callId, 0, @content, 0, @insertTime)";
        OleDbCommand cmd = new OleDbCommand(select, conn);
        cmd.Parameters.AddWithValue("callId", callID.ToString());
        cmd.Parameters.AddWithValue("content", content);
        cmd.Parameters.AddWithValue("insertTime", DateTime.Now.ToString());
        try
        {
            conn.Open();
            cmd.ExecuteScalar();
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
    }
string sql = @"UPDATE tblContent 
                        SET Title = @Title, Content = @Content, IsPublic = @IsPublic, ItemOrder = @ItemOrder
                        WHERE ContentItemID = @ContentItemID";

Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
    db.AddInParameter(cmd, "Title", DbType.String, title);
    db.AddInParameter(cmd, "Content", DbType.String, content);
    db.AddInParameter(cmd, "IsPublic", DbType.Boolean, isPublic);
    db.AddInParameter(cmd, "ItemOrder", DbType.Int32, itemOrder);
    db.AddInParameter(cmd, "ContentItemID", DbType.Int32 , contentItemID);

    db.ExecuteNonQuery(cmd);
}
在本例中,两个数据库的SQL查询字符串也是相同的,但cmd(SqlCommand/OleDbCommand)的类型有所不同


如果有人能就如何避免重复代码和优化给定问题提出建议,我将不胜感激。

您可以使用独立于数据库的接口IDbDataAdapter和IDbCommand,然后使用工厂创建具体实例。这就是一个例子


但是,我建议您使用ORM解决方案,例如如果您的应用程序不是很简单,因为Access和SQL Server之间的SQL语言没有什么区别,这会使您的数据访问代码更加复杂。

您应该看看数据访问位。底层数据库提供程序的细节将为您抽象出来。例如:

public static void AddMessage(string callID, string content)
    {
        string select =
            "INSERT INTO message(key, direction, content, read, write_time) VALUES (@callId, 0, @content, 0, @insertTime)";
        OleDbCommand cmd = new OleDbCommand(select, conn);
        cmd.Parameters.AddWithValue("callId", callID.ToString());
        cmd.Parameters.AddWithValue("content", content);
        cmd.Parameters.AddWithValue("insertTime", DateTime.Now.ToString());
        try
        {
            conn.Open();
            cmd.ExecuteScalar();
        }
        catch (Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
    }
string sql = @"UPDATE tblContent 
                        SET Title = @Title, Content = @Content, IsPublic = @IsPublic, ItemOrder = @ItemOrder
                        WHERE ContentItemID = @ContentItemID";

Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
    db.AddInParameter(cmd, "Title", DbType.String, title);
    db.AddInParameter(cmd, "Content", DbType.String, content);
    db.AddInParameter(cmd, "IsPublic", DbType.Boolean, isPublic);
    db.AddInParameter(cmd, "ItemOrder", DbType.Int32, itemOrder);
    db.AddInParameter(cmd, "ContentItemID", DbType.Int32 , contentItemID);

    db.ExecuteNonQuery(cmd);
}
……或者

string sql = "SELECT MenuText FROM tblMenuItems WHERE MenuItemID = @MenuItemID";

Database db = DatabaseFactory.CreateDatabase();
using(DbCommand cmd = db.GetSqlStringCommand(sql))
{
    db.AddInParameter(cmd, "MenuItemID", DbType.Int32, menuItemID);

    using(IDataReader dr = db.ExecuteReader(cmd))
    {
        while(dr.Read())
        {
            return dr["MenuText"].ToString();
        }
        return null;
    }
}
以上两个示例都适用于Access和MS SQL,如果您坚持使用与Jet和MS SQL兼容的SQL语句,您应该不会遇到任何问题

从Access切换到MS SQL时,只需更改连接字符串,例如,从:

<connectionStrings>
    <add 
         name="ContentManager" 
         connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Content.mdb;" 
         providerName="System.Data.OleDb"/>
</connectionStrings>

…到

<connectionStrings>
    <add
        name="ContentManager"
        connectionString="Data Source=your.sql.server;Initial Catalog=content;Persist Security Info=True;User ID=cmuser;Password=password"
        providerName="System.Data.SqlClient" />
</connectionStrings>

要实现这一点,您只需在EL发行版中引用以下DLL:

Microsoft.Practices.EnterpriseLibrary.Common.dll
Microsoft.Practices.EnterpriseLibrary.Data.dll

很值得一看

干杯

Kev

+1表示SQL中的细微差异。我还建议使用ProviderFactory()