查询&通用

时间:2013-11-27 08:15:41

标签: c# sql generics param dbproviderfactories

我正在开发一个可以访问Oracle的C#解决方案。

并希望有一个关于查询的通用解决方案。

以下是我的代码的一部分:

public DataTable GetData(string query)
{
    DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OracleClient");

    using (DbConnection conn = factory.CreateConnection())
    {
        try
        {
            DbConnectionStringBuilder csb = factory.CreateConnectionStringBuilder();
            csb["Data Source"] = @"Northwind";
            csb["User Id"] = @"Northwind";
            csb["Password"] = @"Northwind";

            conn.ConnectionString = csb.ConnectionString;
            conn.Open();

            using (DbCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = query;

                using (DataTable dt = new DataTable())
                {
                    DbDataAdapter da = factory.CreateDataAdapter();
                    cmd.CommandType = CommandType.Text;
                    da.SelectCommand = cmd;
                    da.Fill(dt);
                    return dt;
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error", ex);
        }
        finally
        {
            if (conn.State != ConnectionState.Closed)
                conn.Close();
        }
    }
}

我称之为我的方法:

DataAccess.Provider data = new DataAccess.Provider();
DataTabel dt = dt.GetData("select * from myTable);

这很不错,但这不是我的目标。

我有一个名为CL_mpg的第二个类,包含我所有的SQL查询。

class CL_MPG
{
    public string rq_sql;

    public string selectParam(string param)
    {
        this.rq_sql = "select * from myTable where id = '" + param + "';";
        return this.rq_sql;
    }

    public string select()
    {
        this.rq_sql = "select * from myTable";
        return this.rq_sql;
    }

    //...

}

我想用我的方法selectParam和/或select填充我的数据表,但我不知道该怎么做。

1 个答案:

答案 0 :(得分:0)

虽然其他人抱怨你的学习尝试,但每个人都必须从某个地方开始。你的方法实际上是一个好的开始,但我会将参数从字符串更改为DbCommand对象。然后,您可以创建方法以正确构建命令并设置适当的参数。然后将整个准备好的命令传递给你的包装器方法(创建连接,测试打开成功,查询数据等)并让你的方法返回一个DataTable对象,就像你一样...

public class CL_MPG
{
   private DataTable GetData(DbCommand cmd )
   {   
      // do all the same as you have with exception of your USING DBCOMMAND.
      // just set the connection property of the incoming command to that of
      // your connection created
      // AT THIS PART -- 
      // using (DbCommand cmd = conn.CreateCommand())
      // {
      //    cmd.CommandText = query;
      // just change to below and remove the closing curly bracket for using dbcommand
      cmd.Connection = conn;
   }

   // Now, your generic methods that you want to expose for querying
   // something like
   public DataTable GetAllData()
   {
      DbCommand cmd = new DbCommand( "select * from YourTable" );
      return GetData( cmd );
   }

   public DataTable GetUser( int someIDParameter )
   {
      DbCommand cmd = new DbCommand( "select * from YourTable where ID = @parmID" );
      cmd.Parameters.Add( "@parmID", someIDParameter );
      return GetData( cmd );
   }

   public DataTable FindByLastName( string someIDParameter )
   {
      DbCommand cmd = new DbCommand( "select * from YourTable where LastName like @parmTest" );
      cmd.Parameters.Add( "@parmTest", someIDParameter );
      return GetData( cmd );
   }
}

请注意,该命令正在构建并完全准备和参数化,而不是字符串的连接,因为先前的注释可能会使您暴露于SQL注入。至于参数,而不是查询Oracle,可能需要对它们进行一些调整。不同引擎使用略有不同的约定。如果连接到SQL-Server数据库,则使用“@”标识参数。在SyBase Advantage数据库中,它使用“:”。使用Visual FoxPro,一个简单的“?”使用占位符。

此外,如果您的查询有许多条件,只需继续添加其他“@parm”类型的占位符,然后按照查询中显示的顺序添加参数,以确保您没有错过任何参数。根据您的需要,某些功能可能没有,一个或多个。然后,在提供的示例中,它就像执行

之类的操作一样简单
DataTable whoIs = yourCL_MPGObject.GetUser( 23 );
if( whoIs.Rows.Count > 0 )
   MessageBox.Show( whoIs.Rows[0]["WhateverColumnName"] );