DataList和SqlDataSource

时间:2014-12-15 19:41:04

标签: c# asp.net

各位程序员都好。

我想对一个数据库进行分页,每个数据库由5个项目组成,并使用打开页面的查询。当我单击按钮时,我想更改数据库连接的查询并刷新数据列表,其中包含我所创建的查询(新的5项)的新数据,但不知怎的,我的代码需要一些帮助。我是一名基本的c#程序员,欢迎各种帮助。

ASP

    <link rel="stylesheet" href="../Images/book-style.css" /> 
    <link rel="stylesheet" href="../Images/form.css" /> 
    <link rel="stylesheet" href="../Images/style.css" /> 
<span id="bookshead" />
    <div style="margin-top:50px" >
        <asp:DataList   ID="DataList1" runat="server" DataKeyField="ID_AUTHOR"  DataSourceID="SqlDataSource1" SeparatorStyle-Wrap="False">

            <ItemTemplate>
               <div class="books" style="width:530px;height:150px;margin-bottom:20px;border:1px dotted black;border-radius:5px;box-shadow:2px 2px 6px black;">
                <p class="book" runat="server"><%# Eval("TITLE") %></p>

                <p class="author"><%# Eval("NAME") %> <%# Eval("SURNAME") %></p>
                <img class="book-image" runat="server" alt="book image" src='<%# Eval("imazhi") %>' style="width:85px;height:130px" />
                <br />

                     <div class="addtowishlist" >
                        <a href="#" >Add to Wishlist</a>

                    </div>
                   </div>
            </ItemTemplate>


        </asp:DataList>
 </div>

<asp:Label runat="server" ID="labe" Text="HELLLOO"></asp:Label>
<form id="ff" runat="server" >
<div id="Navigation" class="navigation">

    <div id="leftnav">
        &nbsp;
        <asp:Button ID="PreviousPageNav" runat="server" href="#bookshead" OnClick="updateBackward" Text="&lt;&lt; Librat e mëparshëm" />
        <asp:Label ID="PagerLocation" runat="server" />
       <asp:Button ID="NextPageNav" runat="server" href="#bookshead" OnClick="updateFoward" Text="&nbsp; Librat e ardhshëm&gt;&gt;"/>
    </div>



</div>
    </form>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>" SelectCommand="Select *FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=1 AND a.ID_AUTHOR<=5"></asp:SqlDataSource>
</asp:Content>

和C#

private int firstItem=1;
private int lastItem=5;
public void updateFoward(object o, EventArgs e)
{
    firstItem += 5;
    lastItem += 5;
    SqlDataSource sql = new SqlDataSource();
    sql.ID = "SqlDataSource1";

    sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
    labe.Text =sql.ID;
    DataList1.DataBind();
}
public void updateBackward(object o,EventArgs e)
{
    firstItem -= 5;
    lastItem -= 5;
    SqlDataSource sql = new SqlDataSource();
    labe.Text = "Backward";
    sql.ID = "SqlDataSource1";
    sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;
    DataList1.DataBind();
}

}

1 个答案:

答案 0 :(得分:1)

此处要解决的第一个问题是firstitemlastitem变量是在页面的类级别定义的。重要的是要记住,ASP.Net中的每个事件都会产生一个全新的类实例,并运行整个页面生命周期:不仅仅是事件代码本身。来自页面类的先前实例的任何内容都消失了。因此,例如,单击“updateForward”按钮,现有代码将始终将结果从6到10运行,无论您单击它多少次。

这里的快速解决方案是将此数据存储在Session或ViewState中,而不是存储在类中。我将继续使用Session作为例子。

第二个问题是代码如下:

sql.SelectCommand = "Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=" + firstItem + "AND a.ID_AUTHOR<=" + lastItem;

这里实际上有两个问题。第一个很容易纠正:在firstItem替换之后,单词“AND”之前没有任何间距。第二个问题将需要更多的工作:“包含参数的字符串连接”技术使您对sql注入开放,应该避免。好消息是,此主要安全问题的解决方案也会产生很好的副作用,使您的数据源再次运行。

首先,让我们先看看一些现有的ASP标记:

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>" 
    SelectCommand="Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>=1 AND a.ID_AUTHOR<=5">
</asp:SqlDataSource>

我们想要将标记更改为:

 <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:eLibraryPConnectionString %>"
     SelectCommand="Select * FROM (AUTHORS a JOIN BOOKS_AUTHORS ba ON a.ID_AUTHOR=ba.ID_AUTHOR) JOIN BOOKS b ON ba.ID_BOOK=b.ID_BOOK WHERE a.ID_AUTHOR>= @firstItem AND a.ID_AUTHOR<= @lastItem">
    <SelectParameters>
        <asp:SessionParameter name="firstItem" sessionfield="firstItem" type="Int32" />
        <asp:SessionParameter name="lastItem" sessionfield="lastItem" type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

如果您想使用ViewState而不是会话,则可以使用asp:ViewStateParameter。还有asp:QueryStringParameters和其他一些你可以使用的选项。

新标记告诉数据源有关sql字符串中占位符的信息,并告诉它在哪里可以找到这些占位符的数据。数据源将处理将数据填充到字符串本身......或者更确切地说,它不会。以这种方式完成查询参数的好处是参数数据永远直接替换为sql命令,即使在数据库服务器上也是如此,消除了sql注入攻击的可能性。

现在您可以简化updateForward()/ Backward()方法,如下所示:

public void updateFoward(object o, EventArgs e)
{
    Session["firstItem"] = (int)Session["firstItem"] + 5;
    Session["lastItem"] = (int)Session["lastItem"] + 5;
    DataList1.DataBind();
}

udpateBackward()方法需要进行类似的更改。切换为长格式x = x + 5而不是x += 5,以便您可以在适当的位置将Object会话值转换为int

您还需要代码来为Session变量设定种子:

public void Page_Load(object o, EventArgs e)
{
    if (!IsPostBack)
    {
         Session["firstItem"] = 1;
         Session["lastItem"] = 5;
    }
}