0

我正在研究一种方法来制作我所有的 SQL 查询,然后将它们数据绑定到中继器、数据列表等等......

protected void sqlQuery(Control controlName, String query) {
    SqlConnection conn = new SqlConnection();
    SqlCommand cmd = new SqlCommand();

    conn.ConnectionString = ConfigurationManager.ConnectionStrings["SqlConn"].ToString();
    cmd.Connection = conn;

    try {
        cmd.CommandText = query;

        DataTable dt = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(cmd);

        adapter.Fill(dt);
        controlName.DataSource = dt;
        controlName.DataBind();

    } catch (Exception error) {
        Label1.Text = "Error!<br/>" + error;
    }
}

然后我会用我想要数据绑定的控件名称调用该方法。像:

sqlQuery(Repeater1, "SELECT * FROM someTable");
sqlQuery(DataList1, "SELECT * FROM someTable");

但是那个剂量现在起作用了,因为当我只使用 Control 时它不知道控制类型。

那么我该怎么做呢?

4

2 回答 2

1

出现问题是因为Control没有您需要的属性/方法,并且这些属性未在接口或基本控件类型上定义。

因此,您必须使用一种称为 反射的东西,这允许您调用所需的属性和方法(以及许多其他东西),而无需任何编译时知识,当然如果您在没有这些的情况下传入控件会得到一个令人讨厌的异常,并且在使用反射时会影响性能 - 但在你的情况下,这将是微不足道的。

我没有方便的 IDE,但应该按照这些思路来做。

public static void DatabindControlFromSqlQuery(Control control,string query)
{
    var connectionString = ConfigurationManager.ConnectionStrings["SqlConn"].ToString(); 
    using (var connection = new SqlConnection(connectionString))
    {
        using (var cmd = new SqlCommand(connection))
        {
            cmd.CommandText = query;
            var dt = new DataTable();
            var adapter = new SqlDataAdapter(cmd);
            adapter.Fill(dt);

            var type = control.GetType();
            var dataSourceProp = type.GetProperty("DataSource");

            dataSourceProp.SetValue(control,dt);

            var dataBindMethod = type.GetMethod("DataBind");
            dataBindMethod.Invoke(control,null);

        }
    }

}

于 2012-10-03T12:02:59.437 回答
0

接受的答案错误地假设.DataSource属性只能通过反射获得。

所有具有此属性的 ASP.NET 控件都派生自,System.Web.UI.WebControls.BaseDataBoundControl因此您可以这样编写代码(无需反射,因此速度会快得多):

protected void sqlQuery(Control controlName, String query) {
    // cast the control to the base class
    var controlWithDataSource = controlName as BaseDataBoundControl;
    if (controlWithDataSource == null)
        throw new ArgumentException("Control does not inherit BaseDataBoundControl.");

    SqlConnection conn = new SqlConnection();
    SqlCommand cmd = new SqlCommand();

    conn.ConnectionString = ConfigurationManager.ConnectionStrings["SqlConn"].ToString();
    cmd.Connection = conn;

    try {
        cmd.CommandText = query;

        DataTable dt = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(cmd);

        adapter.Fill(dt);

        // here reference the new control
        controlName.DataSource = dt;
        controlName.DataBind();

    } catch (Exception error) {
        Label1.Text = "Error!<br/>" + error;
    }
}

您可能可以将方法的签名更改为此类,因此您根本不需要强制转换

protected void sqlQuery(BaseDataBoundControl controlName, String query)
于 2012-11-13T15:11:07.113 回答