我不确定是否已被删除,但我想要做的是创建一个返回查询结果的方法,以便我可以重用连接代码。据我了解,查询返回一个对象,但我如何传回该对象?我想将查询作为字符串参数发送到方法中,并让它返回结果,以便我可以使用它们。这就是我在黑暗中刺伤的东西,它显然不起作用。这个例子是我尝试使用查询结果填充列表框;工作表名称为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();
}
答案 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层或服务架构中的每个层之间进行流水线操作(使其快速),以及这样做的代码开销最小。