创建数据库查询方法

时间:2010-10-23 03:29:32

标签: c# object methods return

我不确定是否已被删除,但我想要做的是创建一个返回查询结果的方法,以便我可以重用连接代码。据我了解,查询返回一个对象,但我如何传回该对象?我想将查询作为字符串参数发送到方法中,并让它返回结果,以便我可以使用它们。这就是我在黑暗中刺伤的东西,它显然不起作用。这个例子是我尝试使用查询结果填充列表框;工作表名称为Employees,字段/列是名称。我得到的错误是“Complex DataBinding接受IList或IListSource作为数据源。”。任何想法?

 public Form1()
        {
            InitializeComponent();
            openFileDialog1.ShowDialog();
            openedFile = openFileDialog1.FileName;

            lbxEmployeeNames.DataSource = Query("Select [name] FROM [Employees$]");


        }

        public object Query(string sql)
        {
            System.Data.OleDb.OleDbConnection MyConnection;
            System.Data.OleDb.OleDbCommand myCommand = new System.Data.OleDb.OleDbCommand();
            string connectionPath;

            //build connection string
            connectionPath = "provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + openedFile + "';Extended Properties=Excel 8.0;";

            MyConnection = new System.Data.OleDb.OleDbConnection(connectionPath);
            MyConnection.Open();
            myCommand.Connection = MyConnection;

            myCommand.CommandText = sql;
            return myCommand.ExecuteNonQuery();


        }

4 个答案:

答案 0 :(得分:24)

答案 1 :(得分:2)

请尝试使用ExecuteReader。它返回一个对象,然后可以像文件一样读取以获得结果:

OleDbDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
while(myReader.Read()) 
{
   Console.WriteLine(myReader.GetString(0));
}

答案 2 :(得分:2)

喂!试试这个, 如果您只想将所有员工的姓名显示在listBox中,这应该可行。 我刚编辑了代码中的一些行......

Form1()
{
    InitializeComponent();
    openFileDialog1.ShowDialog();
    openedFile = openFileDialog1.FileName;

    lbxEmployeeNames.DataSource = Query("Select [name] FROM [Employees$]");
    lbxEmployeeNames.DisplayMember = "name"; // The column you want to be displayed in your listBox.
}

// Return a DataTable instead of String.
public DataTable Query(string sql)
{
    System.Data.OleDb.OleDbConnection MyConnection;
    string connectionPath;

    //build connection string
    connectionPath = "provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + openedFile + "';Extended Properties=Excel 8.0;";

    MyConnection = new System.Data.OleDb.OleDbConnection(connectionPath);
    MyConnection.Open();
    System.Data.OleDb.OleDbDataAdapter myDataAdapter = new System.Data.OleDb.OleDbDataAdapter(sql, MyConnection);
    DataTable dt = new DataTable();
    myDataAdapter.Fill(dt);
    return dt;
}

答案 3 :(得分:0)

发布代码的巨大问题是无法正确参数化查询。在调用函数之前,你必须进行字符串连接,这使你对sql注入攻击开放。您需要在代码中使用一种方法来允许查询参数与sql字符串分开。

示例中的其他一些问题包括未正确关闭连接(如果查询引发异常,它将保持挂起状态)并调用错误的ADO方法。

我已经付出了很多努力来实现这一目标,我认为我有一些接近理想模式的东西,因为你希望在我对另一个问题的答案中得到很好的指导: Fastest method for SQL Server inserts, updates, selects

基本上,当您调用ADO函数来实际运行查询时,您将返回DbDataReader。我使用迭代器块将该数据读取器转换为IEnumerable< IDataRecord>适用于linq和其他代码,以及Action< SqlCommand>鼓励正确的查询参数化。因此,您将连接代码抽象为如下方法:

private static IEnumerable<IDataRecord> Retrieve(string sql, Action<SqlParameterCollection> addParameters)
{
    using (var cn = new SqlConnection(ConnectionString))
    using (var cmd = new SqlCommand(sql, cn))
    {
        addParameters(cmd.Parameters);

        cn.Open();
        using (var rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
                yield return rdr;
            rdr.Close();
        }
    }
}

并在代码中使用它来实现这样的实际查询:

public IEnumerable<IDataRecord> GetSomeDataById(int MyId)
{
    return Retrieve(
        "SELECT * FROM [MyTable] WHERE ID= @MyID", 
       p =>
       {
          p.Add("@MyID", SqlDbType.Int).Value = MyId;
       }
     );
}

请注意,这是让您正确地参数化查询,始终正确关闭和处理您的连接对象,设置您在3层或服务架构中的每个层之间进行流水线操作(使其快速),以及这样做的代码开销最小。