וובמאסטר - תיכנות ובניית אתרים

עבודה מול מסדי נתונים ב-asp.net

ירדן שם טוב/‏ 8 אוגוסט, 2003
F+
F-

האובייקט DataSet

השינוי המשמעותי שבין ado ל ado.net הוא האובייקט dataSet שבא להחליף את האובייקט RecordSet. בניגוד לrecordSet שסיפק אפשרות לוהצגת שורות ממסד נתונים באופן פשוט, dateSet מסוגל להרבה יותר.
dataSet מכיל קבוצות שלמות של נתונים. הוא מסוגל להכיל מספק טבלאות בוא זמנית, קשרים בין טבלאות אילוצים שונים ועוד.

שימוש באובייקט DataSet

ברוב המקרים נמלא את הdataset שלנו ממקור נתונים קיים, בדר"כ מסד נתונים כלשהו, אך ניתן להשתמש בוא גם ידנית, כלומר ליצור dataset ולהכניס אליו נתונים. דוגמה לשימוש:
  <%@ Import Namespace =system %>
  <%@ Import Namespace =system.data %>
 <script runat =server >
 Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
   Dim ds1 As New DataSet("DataSet1")
   
   Dim ds1Table As New DataTable("Colors")
   ds1Table.Columns.Add("ColorId", Type.GetType("System.Int32"))
   ds1Table.Columns.Add("ColorName", Type.GetType("System.String"))
   ds1Table.Columns("ColorId").AutoIncrement = True
   
   ds1.Tables.Add(ds1Table)
   
   Dim row1 As DataRow = ds1Table.NewRow
   row1(1) = "אדום"
   ds1Table.Rows.Add(row1)
  End Sub
 </script>  

ראשית יש לייבא את מרחב השמות system.data שבתוכו קיים אובייקט הdataset.
תחילה הגדרנו משתנה ds1 מסוג dataset. לאחר מכן הגדרנו משתנה מסוג datatable בשם colors. לאחר הכרזת הטבלה אנו מזינים את שמות העמודות וסוגי הנתונים שלהן:
  • colorID מסוג מספר
  • ColorName מסוג מחרוזת
לאחר מכן הכרזנו כי colorId יהיה מספור אוטומטי. לאחר מכן הוספנו לdataset שלנו את הטבלה.
בכדי להוסיף נתונים יצרנו datarow וקישרנו אותה לטבלה שיצרנו קודם לכן, הצבנו בColorName שהוא בעל אינדקס 1 את הערך אדום והוספנו את העמודה לטבלה.
זהו באופן בסיסי עיקרון הdataset, משום שברוב המקרים לא נצטרך ליצור בעצמנו את הdataset ומבנהו לא דרוש הסבר מורחב על אפשרותיו ברגע זה.

מילוי DataSet ממקור נתונים קיים

תחילה נכין מקור נתונים: טבלה בaccess:

לאחר שיש לנו מסד נתונים כל מה שנותר הוא להשתמש בוא בכדי למלא dataset. מילוי הdataset נעשה באופן הבא:
<%@ Import Namespace =system %>
<%@ Import Namespace =system.data %>
<%@ Import Namespace =system.data.oledb %>
<script runat =server >
Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
  Dim conn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" + Server.MapPath("db.mdb"))
  Dim cmd As New OleDbDataAdapter("Select * from users", conn)
  Dim ds1 As DataSet = New DataSet()
  cmd.Fill(ds1, "users")
End Sub
</script>


ראשית יבאנו את מרחבי השמות data: לשימוש בdataset ו data.oledb לשימוש באובייקטים של oledb כדי לקשר למסד נתונים חיצוני.
בשורה הראשונה הגדרנו conn מסוג oledbconntection ובוא את מחרוזת החיבור למסד הנתונים הרצוי. לאחר מכן הגדרנו את cmd מסוג oledbdataAdapter והשתמשנו בוא בכדי לשלוף את הנתונים מהטבלה שלנו. הכרזנו על dataset חדש בשם ds1 ומילאנו אותו בטבלה users בעזרת הפקודה fill של OleDbDataAdapter.

הפקדים Repeater,DataList ו DataGrid

בכדי להציג נתונים שאיכסנו בdataset קיימים שלושה פקדים מרכזיים: Repeater,DataList ו DataGrid.
Repeater
פקד repeater הינו הפשוט מבין השלושה, הוא מספק כתיבת הופעת נתונים וחוזר עליה לאורך כל הנתונים.
בפקד זה יש להשתמש במבנים הבאים בכדי להציג את הנתונים:
  • ItemTemplate-בתבנית זו אתה שם את עיצוב הנתונים(תבנית זו הינה חובה בכל repater)
  • AlternatingItemTemplate-תבנית המוצגת בעבור כל שורת נתונים זוגית-לא חובה
  • HeaderTemplate-יופיע בתחילת הצגת הנתונים
  • footerTemplate-יופיע בסוף הצגת הנתונים
  • SeparatorTemplate-תבנית זו תוצג בין כל שורת נתונים
דוגמה לשימוש בrepeater:
<%@ Import Namespace =system %>
<%@ Import Namespace =system.data %>
<%@ Import Namespace =system.data.oledb %>
<script runat =server >
   Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
        Dim conn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" + Server.MapPath("db.mdb"))
        Dim cmd As New OleDbDataAdapter("Select * from users", conn)
        Dim ds1 As DataSet = New DataSet()
        cmd.Fill(ds1, "users")

        rep1.DataSource = ds1
        rep1.DataBind()
   End Sub
</script>
<html >
    <body dir =rtl>
        <asp:Repeater runat =server ID=rep1>
        <HeaderTemplate >
            <table border =1 >
            <tr>
                <th>שם משתמש</th>
                <th>סיסמה</th>
            </tr>
            </HeaderTemplate>
            <ItemTemplate >
            <Tr>
                <td> 
                <%#Container.DataItem("username")%>
                </td>
                <td>
                <%#Container.DataItem("userpassword")%>
                </td>
            </Tr>
            </ItemTemplate>
            <alternatingItemTemplate >
            <Tr bgcolor =silver >
                <td > 
                <%#Container.DataItem("username")%>
                </td>
                <td>
                <%#Container.DataItem("userpassword")%>
                </td>
            </Tr>
            </alternatingItemTemplate>
            <FooterTemplate >
            </table>
        </FooterTemplate>
        </asp:Repeater>
    </body>
</html> 

דבר ראשון מילאנו dataset בנתונים, לאחר מכן השמנו לתכונה datasource של repeater את הdataset ,והפעלנו את השגרה dataBind() בכדי להשתמש בקישור לנתונים שנמצאים בתוך הrepeater שלנו.
בקוד שלנו יצרנו repeater בעל כמה תבניות. בכדי להציג את שדות הנתונים השתמשנו בקישור נתונים שאופשר ע"י ה databind והוא מבוצע כך:
<%#Container.DataItem("theField")%>  

והתוצאה:

כמו לכל פקד שרת גם לrepeater קיימים אירועים:
לדוגמה: ItemCreated-קורה לפני שנוצרת תבנית חדשה ,יש לטפל באירוע זה באופן הבא:
.
.
.
Sub rep1ItemCreated(ByVal obj As Object, ByVal e As RepeaterItemEventArgs)
    Response.Write(e.Item.ItemType.ToString + "<Br>")
End Sub
.
.
.
<asp:Repeater OnItemCreated=rep1ItemCreated runat =server ID=rep1>
.
.
.


DataList
פקד שרת זה דומה לrepeater ,אך יש לו עוד שתי תבניות :
  • SelectedItemTemplate-יופיע כאשר נבחר פריט ספציפי בפקד
  • EditItemTemplate-מאפשרת מצב עריכה לפריט
בחירת פריטים
אופן בחירת פריטים מתבצע באופן הבא: פקד שרת שנמצא בתוך הdatalist מופעל, כאשר הוא מופעל בעזרת האירוע onItemCommand של datalist אנו מזהים שהוא הופעל וניגשים לשגרה שבה אנו מפעילים את תבנית הפריט הנבחר.
דוגמה לשימוש:
<%@ Import Namespace =system %>
<%@ Import Namespace =system.data %>
<%@ Import Namespace =system.data.oledb %>
<script runat =server >
Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
    Dim conn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" + Server.MapPath("db.mdb"))
    Dim cmd As New OleDbDataAdapter("Select * from users", conn)
    Dim ds1 As DataSet = New DataSet()
    cmd.Fill(ds1, "users")

    dl1.DataSource = ds1
    DataBind()
End Sub

Sub dl1ItemCommand(ByVal obj As Object, ByVal e As DataListCommandEventArgs)
    dl1.SelectedIndex = e.Item.ItemIndex
    dl1.DataBind()
End Sub
</script>
<html >
    <body dir =rtl>
        <form runat =server >
        <asp:DataList GridLines =Both CellPadding =5
        OnItemCommand=dl1ItemCommand runat =server ID=dl1 RepeatLayout=table RepeatDirection =Vertical DataKeyField =userid>
        <ItemTemplate >
        <asp:linkButton runat =server Text ='<%# container.dataitem("username") %>' CommandName =select ></asp:linkButton> 
        </ItemTemplate>
        <SelectedItemTemplate >
        <div>
        הסיסמה של: <%# container.dataitem("username") %> היא:
        <%# container.dataitem("userpassword") %>
        </div>
        </SelectedItemTemplate>
        </asp:DataList>
        </form>
    </body>
</html> 


כמו עם הrepeater מילאנו את הdatalist בנתונים.
מבנה הdatalist הולך כך: ראשית כל הגדרנו לו כמה תכונות עיצוב שונות ואת שתי התכונות הבאות:
  • OnItemCommand-אירוע. מתבצע בעת שימוש בפקד שרת מתוך הdatalist
  • DataKeyField -משתמש בכדי לתת לכל רשומה מהמסד נתונים מספר יוחדי, רצוי כי הערך לתכונה זו יהיה כזה שלא יחזור על עצמו פעמיים.
בתוך הdatalist השתמשנו בשתי תבניות הראשונה היא תבנית הנתונים הראשונה שיראו ובה יש פקד שרת linkbutton אשר בעת לחיצה עליו תבנית ה selecteditemteplate תיגלה.
בעת לחיצה על הLinkbutton בגלל שהגדרנו את התכונה OnItemCommand=dl1ItemCommand אז נגיע לשגרה dl1ItemCommand ושם קעבנו כי הפריט הנבחר יהיה הindex שנלחץ.
וזוהי התוצאה:

לאחר לחיצה על הפריט השני אנו מגלים את הseleceditemtemplate שלו.
עריכת פריטים
עוד אפשרות שהdatalist מספק הוא עריכת פריטים.
הדבר מתבצע כך:
בקוד הקודם ניתן לראות שלlinkbutton ניתנה התכונה commandname , ע"י זו ניתן לבדוק איזה כפתור נלחץ, ובעזרת ההגדרה של הdatakeyfield ניתן לזהות את הuserid שניבחר ובכך להפעיל משפט sql שיעדכן את הרשומות.
אופן הכתיבה מתבצע כך:
<%@ Import Namespace =system %>
<%@ Import Namespace =system.data %>
<%@ Import Namespace =system.data.oledb %>
<script runat =server >
Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
    Dim conn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" + Server.MapPath("db.mdb"))
    Dim cmd As New OleDbDataAdapter("Select * from users", conn)
    Dim ds1 As DataSet = New DataSet()
    cmd.Fill(ds1, "users")

    dl1.DataSource = ds1
    DataBind()
End Sub

Sub dl1EditCommand(ByVal obj As Object, ByVal e As DataListCommandEventArgs)
    dl1.EditItemIndex = e.Item.ItemIndex
    dl1.DataBind()
End Sub

Sub dl1CancelCommand(ByVal obj As Object, ByVal e As DataListCommandEventArgs)
    dl1.EditItemIndex = -1
    dl1.DataBind()
End Sub

Sub dl1UpdateCommand(ByVal obj As Object, ByVal e As DataListCommandEventArgs)
    Response.Write("נערך")
    dl1.DataBind()
End Sub

Sub dl1DeleteCommand(ByVal obj As Object, ByVal e As DataListCommandEventArgs)
    Response.Write("נמחק")
    dl1.DataBind()
End Sub
</script>
<html >
<body dir =rtl>
    <form runat =server >
        <asp:DataList GridLines =Both CellPadding =5 runat =server ID=dl1 RepeatLayout=table RepeatDirection =Vertical DataKeyField =userid
        OnDeleteCommand =dl1DeleteCommand
        OnCancelCommand =dl1CancelCommand
        OnEditCommand =dl1EditCommand
        OnUpdateCommand =dl1UpdateCommand>

        <ItemTemplate >
            <asp:linkButton runat =server Text ='<%# container.dataitem("username") %>' CommandName =edit ></asp:linkButton> 
        </ItemTemplate>
        <EditItemTemplate >
        <asp:LinkButton runat =server CommandName =Cancel Text =חזור></asp:LinkButton><br />
        <asp:LinkButton runat =server CommandName =Delete Text =מחק></asp:LinkButton><br />
        <asp:LinkButton runat =server CommandName=Update Text =ערוך></asp:LinkButton>
        </EditItemTemplate>
        </asp:DataList>
    </form>
</body>
</html> 


בdatalist הוספנו עוד ארבעה אירועים:
  • OnDeleteCommand-כאשר נלחץ כפתור המחיקה
  • OnCancelCommand-כאשר נלחץ כפתור החזרה
  • OnEditCommand-כאשר נלחץ כפתור העריכה
  • OnUpdateCommand-כאשר נלחץ כפתור העריכה
יצרנו תבנית חדשה בשם editItemTemplate ובה שמנו את שלושת הכפתורים ולכל אחד נתנו את הcommandname שלו כדי שנוכל להבדיל כל כפתור לאיזו מטרה הוא שייך.
כמוכן נוספו שגרות לקוד:
  • dl1EditCommand-בה אנו קובעים איזה בלוק עריכה נראה לפי מה שנבחר
  • dl1CancelCommand-בה אנו יוצאים מהבחירה ע"י השמה של -1 אשר לא יכול להיווצר פריט עם מספר סידורי כזה ,ולכן שום פריט לא יהיה נבחר.
  • dl1UpdateCommand-שם יש להכניס את הפעולות של העריכה לפי הצרכים האישיים
  • dl1DeleteCommand-שם יש להכניס את הפעולות של המחיקה
והינה התוצאה:

DataGrid
אם datalist מספק אפשרויות רבות, הרי שהdataGrid מספק אף יותר.datagrid מציג את הנתונים בצורת טבלה וכברירת מחדל נותן לכל עמודה שורה בטבלה, אך כמובן ניתן לערווך באופן ידני את שיטת התצוגה.
להלן סוגי העמודות:
  • BoundColumn-מאפשר לציין איזה עמודה להציג ותכונות עיצוב שלה.
  • HyperLinkColumn-עמודה שמציגה נתון כקישור
  • ButtonColumn-עמודה אשר מציגה לחצן
  • EditCommandColumn-מאפשרת לערוך את הפריטים, מחליפה את העמודות בתיבות טקסט
  • TemplateColumn-להגדרת עיצוב המשתמש בכמה נתונים
דוגמה לשימוש בdatagrid:
<%@ Import Namespace =system %>
<%@ Import Namespace =system.data %>
<%@ Import Namespace =system.data.oledb %>
<script runat =server >
Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
    Dim conn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" + Server.MapPath("db.mdb"))
    Dim cmd As New OleDbDataAdapter("Select * from users", conn)
    Dim ds1 As DataSet = New DataSet()
    cmd.Fill(ds1, "users")

    dg1.DataSource = ds1
    DataBind()
End Sub
</script>
<html >
<body dir =rtl>
    <form runat =server >
    <asp:DataGrid ID=dg1 runat =server AutoGenerateColumns =false CellPadding =5 >
    <Columns >
    <asp:BoundColumn HeaderText="שם משתמש" DataField ="username"></asp:BoundColumn>
    <asp:BoundColumn HeaderText ="סיסמה" DataField ="userpassword"></asp:BoundColumn>
    <asp:ButtonColumn HeaderText ="מחיקה" Text ="מחק" CommandName ="delete" ButtonType =LinkButton ></asp:ButtonColumn>
    </Columns>
    </asp:DataGrid>
    </form>
</body>
</html> 


תחילה יצרנו את פקד הdatagrid וקעבנו כי לא יצור את כל העמודות באופן אוטומטית ע"י קבעית התכונה autoGenerateColumns ל שקר. לאחר מכן יצרנו שלוש עמודות: שתי עמודות מסוג boundColumn להצגת טקסט ועמודת כפתור שתשמש למחיקה בעתיד.
וכך זה יוצא:

עריכת פריטים באמצעות ה datagrid
תכונה מיוחדת של הdatagrif היא שניתן לעדכן את הפריטים, בעת לחיצה על כפתור כל שדות הטקסט נהפכים לפריטים הניתנים לעריכה. בכדי לערוך פריטים יש להשתמש באירוע oneditcommand באופן הבא:
<%@ Import Namespace =system %>
<%@ Import Namespace =system.data %>
<%@ Import Namespace =system.data.oledb %>
<script runat =server >
Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
    Dim conn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" + Server.MapPath("db.mdb"))
    Dim cmd As New OleDbDataAdapter("Select * from users", conn)
    Dim ds1 As DataSet = New DataSet()
    cmd.Fill(ds1, "users")

    dg1.DataSource = ds1
    DataBind()
End Sub

Sub dg1pagechanged(ByVal obj As Object, ByVal e As DataGridPageChangedEventArgs)
    dg1.CurrentPageIndex = e.NewPageIndex
    dg1.DataBind()
End Sub
</script>
<html >
<body dir =rtl>
    <form runat =server >
    <asp:DataGrid ID=dg1 runat =server AutoGenerateColumns =false CellPadding =5 
    AllowPaging =true 
    OnPageIndexChanged =dg1PageChanged
    PagerStyle-Mode =numericPages
    PagerStyle-PageButtonCount =4
    PageSize =2
    >

    <Columns >
    <asp:BoundColumn HeaderText="שם משתמש" DataField ="username"></asp:BoundColumn>
    <asp:BoundColumn HeaderText ="סיסמה" DataField ="userpassword"></asp:BoundColumn>
    </Columns>
    </asp:DataGrid>
    </form>
</body>
</html> 

הוספנו לdatagrid שלושה אירועים:OnEditCommand,OnCancelCommand ו onUpdateCommand אירועים אלו דומים מאד לאלו של הdatalist.נוספה עמודה חדשה מסוג editCommandColumn ובה סוגי הכפתורים השונים שיהיו בה:כפתור חזרה, כפתור עידכון וכפתור עריכה. בעת שנלחץ כפתור הוא שולח את העמוד לשגרה שלו ושם מתבצעות הפעולות השונות שדומות מאד לאלו של הdatalist.
והינה התוצאה:

חלוקה לדפים
dataGrid מאפשרת חלוקה לעמודים בצורה אוטומטית. בעזרת התכונה allowPaging ניתן לקבוע שהעמודות שלנו יחולקו לעמודים. בנוסף לתכונה זו יש להפעיל את האירוע OnPageIndexChanged שתופעל בעת שינוי עמוד, כדי לקבוע את כמות הרשומות בעמוד יש להשתמש ב pageSize. אופן השימוש הוא כזה:
<%@ Import Namespace =system %>
<%@ Import Namespace =system.data %>
<%@ Import Namespace =system.data.oledb %>
<script runat =server >
Sub page_load(ByVal obj As Object, ByVal e As EventArgs)
    Dim conn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" + Server.MapPath("db.mdb"))
    Dim cmd As New OleDbDataAdapter("Select * from users", conn)
    Dim ds1 As DataSet = New DataSet()
    cmd.Fill(ds1, "users")

    dg1.DataSource = ds1
    DataBind()
End Sub

Sub dg1EditCommand(ByVal obj As Object, ByVal e As DataGridCommandEventArgs)
    dg1.EditItemIndex = e.Item.ItemIndex
    dg1.DataBind()
End Sub
Sub dg1UpdateCommand(ByVal obj As Object, ByVal e As DataGridCommandEventArgs)
    Response.Write("updated")
    Dim newUsername, newPassword As String
    newUsername = CType(e.Item.Cells(1).Controls(0), TextBox).Text
    newPassword = CType(e.Item.Cells(2).Controls(0), TextBox).Text 
    dg1.DataBind()
End Sub
Sub dg1CancelCommand(ByVal obj As Object, ByVal e As DataGridCommandEventArgs)
    dg1.EditItemIndex = -1
    dg1.DataBind()
End Sub
</script>
<html >
<body dir =rtl>
    <form runat =server >
    <asp:DataGrid ID=dg1 runat =server AutoGenerateColumns =false CellPadding =5 
    OnEditCommand =dg1EditCommand
    OnCancelCommand =dg1CancelCommand
    OnUpdateCommand =dg1UpdateCommand>

    <Columns >

    <asp:BoundColumn HeaderText="שם משתמש" DataField ="username"></asp:BoundColumn>
    <asp:BoundColumn HeaderText ="סיסמה" DataField ="userpassword"></asp:BoundColumn>
    <asp:EditCommandColumn EditText ="ערוך" UpdateText ="שנה" CancelText ="חזור" Headertext="עריכה"></asp:EditCommandColumn>
    </Columns>
    </asp:DataGrid>
    </form>
</body>
</html> 


לdatagrid הוספנו מספר תכונות: ראשית כל איפשרנו דפדוף, קבענו שבעת אירוע שינוי עמוד השגרה dg1pagechanged תופעל סגנון העימוד יהיה מספרים ויראו 4 מספרים בכל פעם. בשגרה של שינוי העמוד קבענו את העמוד הנוכחי בעזרת התכונה CurrentPageIndex.
וכך זה נראה:
תגיות: DataSet‏  /  asp.net‏  /  db‏  /  database‏  /  בסיס נתונים‏  /  DataGrid‏  /  Repeater‏  

תגובות בפייסבוק

תגובות למאמר



תגיות פופולאריות

X
הצטרף לעמוד שלנו בפייסבוק להישאר מעודכן!
וובמאסטר © כל הזכויות שמורות