SqlDataSource 更好的解决方案?

Better solution to SqlDataSource?

我需要在我网站的多个页面上显示来自 SQL 服务器数据库中视图的一些数据。我通过在我的 web.config 中使用 SqlDataSource 然后在我的 .aspx 页面中使用 GridView 控件来显示数据。

现在,这可行,但我在一些论坛上看到使用 SqlDataSource 是不好的做法?将来我可能需要 admin/user 过滤数据的能力,所以我不确定这将如何与我当前的实现一起使用。

到目前为止,我的代码如下所示:

web.config 文件中:

<connectionStrings>
    <add name="Test1.ConnectionString" 
         connectionString="Data Source=...."
         providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
</system.web>

在我的 aspx 中有这样的东西

<body id="wrap" >
  <form  runat="server">
    <asp:GridView ID="GridView1" runat="server" AllowSorting="True" AutoGenerateColumns="False" 
         BackColor="White" BorderColor="#CCCCCC" 
         BorderStyle="None" BorderWidth="1px" CellPadding="3" 
         DataSourceID="SqlDataSource1" Height="500px" Width="408px">
        <Columns>
            <asp:BoundField DataField="Title" HeaderText="Title" ReadOnly="True" SortExpression="Title">
                <ItemStyle Width="400px" HorizontalAlign="Center" Height="100px" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" />
            </asp:BoundField>
            <asp:BoundField DataField="Result" HeaderText="Result" ReadOnly="True" SortExpression="Result" >
                <ItemStyle HorizontalAlign="Center" Height="100px" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" />
            </asp:BoundField>
        </Columns>
        <FooterStyle BackColor="White" ForeColor="#002756" />
        <HeaderStyle BackColor="#003466" Font-Bold="True" ForeColor="White" />
        <PagerStyle BackColor="White" ForeColor="#002756" HorizontalAlign="Left" />
        <RowStyle ForeColor="#002756" />
    </asp:GridView>
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
         ConnectionString="<%$ ConnectionStrings: Test1.ConnectionString %>" 
         SelectCommand="SELECT * FROM [Test1.ConnectionString]"> 
    </asp:SqlDataSource>
  </form>
</body>

所以我的问题是有没有更好的方法来实现这个,请记住,我可能需要 user/admin 的函数来按特定条件过滤数据?

使用 SqlDataSource 不一定是不好的做法...但它确实倾向于将您的数据访问代码与您的表示代码混合在一起。此外,使用 ObjectDataSource 包裹您的视图通常可以做得更好。涉及的代码有点多(您必须在视图中的 select 某处创建一个新的 class ),但您最终得到的方法可以在将来轻松更新或替换以处理您可能需要的任何更改。

您可以通过编程方式设置网格视图的数据源。

    protected void Page_Load(object sender, EventArts e)
    {
        using(SqlConnection conn = new SqlConnection(connectionString))
        {
            string query = "SELECT * FROM Test"; //your SQL query goes here
            SqlCommand cmd = new SqlCommand(query, conn);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataTable table = new DataTable();
            da.Fill(table);

            GridView1.DataSource = table;
            GridView1.DataBind();

            cmd.Dispose();
            da.Dispose();
        }
    }

正如我在评论中提到的,我建议您使用后面的代码来实现这一点,因为如果将来需要,进行更改会容易得多。我假设您的数据库中有一个名为 Test1 的 table。我们将首先创建一个 class 来在 C# 中表示它,并添加一些我们稍后将使用的属性。

public class Test
{
  public string Title { get; set; }
  public int Result { get; set; }
}

现在让我们创建一个方法,该方法 returns 来自您数据库的值集合。

public List<Test> GetData()
{
    List<Test> myList = new List<Test>();

    string sqlQuery = "Select Title, Result From Test";
    string connectionString = ConfigurationManager.ConnectionStrings["Test1.ConnectionString"].ConnectionString; //Read connection string from config file

    using (var con = new SqlConnection(connectionString))
    {
        using (var cmd = new SqlCommand(sqlQuery, con))
        {
            //Add param here if required.
            con.Open(); //Open connection
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    Test t = new Test();
                    t.Title = reader["Title"].ToString();
                    t.Result = Convert.ToInt32(reader["Result"]);

                    myList.Add(t);
                }
            }
        }
    }
    return myList;
}

最后,您要为 GridView 设置数据源。我假设您有一个名为 MyGridPage.aspx 的页面,打开 MyGridPage.asps.cs 并且在您的 Page_Load 事件中,您可以将网格的 DataSource 设置为:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Test t = new Test();
        GridView1.DataSource = t.GetData();
        GridView1.DataBind();
    }
}

如果您想通过例如用户名过滤您的 Sql 查询,您可以将其更改为:

string sqlQuery = "Select Title, Result From Test Where username = @username";

那么就可以传入@username参数为:

cmd.Parameters.Add("@username", SqlDbType.NVarChar).Value = myUsername;

myUsername 可以是登录到您的应用程序的人。您将在打开连接之前传递参数。传递参数也将防止 sql 注入,我建议你阅读以防你不知道。

注意:建议使用using块来保证连接对象的关闭和正确处理。