Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Best Practise για GRUD operation

Îåêßíçóå áðü ôï ìÝëïò koslyr. Τελευταία δημοσίευση από το μέλος George J. Capnias στις 19-04-2012, 19:21. Υπάρχουν 18 απαντήσεις.
Σελίδα 1 από 2 (19 εγγραφές)   1 2 >
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  12-04-2012, 15:43 69994

    Best Practise για GRUD operation

    Σχεδόν το 99% των web applications που έχω αναπτύξει έχουν από πίσω τους μια βάση δεδομένων (MSSQLServer, MSAccess, MySQL).
    Θεωρώ ότι όλοι μας θα θέλαμε ο κώδικας των ενεργειών (select, insert, update, delete) που διαχειρίζεται τα δεδομένα της βάσης να είναι τυποιημένος με τον βέλτιστο τρόπο, ώστε να μας επιτρέπει την άμεση επαναχρησιμοποίηση τόσο εντός του ίδιου του project όσο και σε διάφορα ανεξάρτητα μεταξύ τους project.

    1) Έχοντας για παράδειγμα την γνωστή βάση Northwind, αρχικά ξεκίνησα ενδεικτικά την τοποποίηση αυτή φτιάχνοντας μια class clsProducts.cs για την διαχείριση του πίνακα Products:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    public class ClsProducts
    {
    private string strSql;
    private string strCon;

    private long productid;
    private string productname;
    private long supplierid;
    private long categoryid;
    private float unitprice;
    private int quantity;

    // Property read-only
    public long ProductID
    {
    set { productid = value; }
    get { return productid; }
    }

    public string ProductName
    {
    set { productname = value; }
    get { return productname; }
    }

    public long SupplierID
    {
    set { supplierid = value; }
    get { return supplierid; }
    }

    public long CategoryID
    {
    set { categoryid = value; }
    get { return categoryid; }
    }

    public float UnitPrice
    {
    set { unitprice = value; }
    get { return unitprice; }
    }

    public int Quantity
    {
    set { quantity = value; }
    get { return quantity; }
    }


    // TODO: Add constructor logic here
    public ClsProducts()
    {
    strCon = ClsWebConfig.GetConnectionString();
    }


    public string SetSqlQuery(int CategoryID=-1)
    {
    strSql = "SELECT ProductID, Products.CategoryID, Products.SupplierID, ProductName, CategoryName, CompanyName, UnitPrice, UnitsInStock ";
    strSql += "FROM Categories INNER JOIN (Suppliers INNER JOIN Products ON Suppliers.SupplierID = Products.SupplierID) ON Categories.CategoryID = Products.CategoryID ";
    if (CategoryID != -1)
    {
    strSql += "WHERE Products.CategoryID=" + CategoryID + " ";
    }
    strSql += "ORDER by CategoryName, CompanyName, ProductName ";

    return strSql;
    }


    public DataSet FetchCategoryType()
    {
    strSql = "SELECT CategoryID, CategoryName FROM Categories";
    OleDbDataAdapter da = new OleDbDataAdapter(strSql, strCon);
    DataSet ds = new DataSet();
    da.Fill(ds);
    return ds;
    }

    public DataSet FetchSuppliersType()
    {
    strSql = "SELECT SupplierID, CompanyName FROM Suppliers";
    OleDbDataAdapter da = new OleDbDataAdapter(strSql,strCon);
    DataSet ds = new DataSet();
    da.Fill(ds);
    return ds;
    }

    //Make the Insert
    public void Insert()
    {
    strSql = "INSERT INTO Products (ProductName, SupplierID, CategoryID, UnitPrice, UnitsInStock) ";
    strSql += "VALUES (@productname, @supplierid, @categoryid, @unitprice, @quantity)";
    // Create Connection
    OleDbConnection MyCnn = new OleDbConnection(strCon);

    // Create Command
    OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
    MyCmd.Parameters.Add("@productname", OleDbType.VarChar, 40).Value = productname;
    MyCmd.Parameters.Add("@supplierid", OleDbType.BigInt).Value = supplierid;
    MyCmd.Parameters.Add("@categoryid", OleDbType.BigInt).Value = categoryid;
    MyCmd.Parameters.Add("@unitprice", OleDbType.Double).Value = unitprice;
    MyCmd.Parameters.Add("@quantity", OleDbType.Integer).Value = quantity;

    MyCnn.Open();
    MyCmd.ExecuteNonQuery();
    MyCnn.Close();
    }

    //Make the Update
    public void Update()
    {
    strSql = "UPDATE Products ";
    strSql += "SET ProductName=@productname, SupplierID=@supplierid, CategoryID=@categoryid, ";
    strSql += "UnitPrice=@unitprice, UnitsInStock=@quantity ";
    strSql += "WHERE ProductID=@productid";
    // Create Connection
    OleDbConnection MyCnn = new OleDbConnection(strCon);
    try
    {
    // Create Command
    OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
    MyCmd.Parameters.Add("@productname", OleDbType.VarChar, 40).Value = productname;
    MyCmd.Parameters.Add("@supplierid", OleDbType.BigInt).Value = supplierid;
    MyCmd.Parameters.Add("@categoryid", OleDbType.BigInt).Value = categoryid;
    MyCmd.Parameters.Add("@unitprice", OleDbType.Double).Value = unitprice;
    MyCmd.Parameters.Add("@quantity", OleDbType.Integer).Value = quantity;
    MyCmd.Parameters.Add("@productid", OleDbType.BigInt).Value = productid;

    MyCnn.Open();
    MyCmd.ExecuteNonQuery();
    }
    catch (Exception err)
    {
    throw err;
    }
    finally
    {
    MyCnn.Close();
    }

    }

    //Make the Update(Product-UnitPrice)
    public void UpdateProductUnitPrice()
    {
    strSql = "UPDATE Products ";
    strSql += "SET UnitPrice=@unitprice ";
    strSql += "WHERE ProductID=@productid";
    // Create Connection
    OleDbConnection MyCnn = new OleDbConnection(strCon);
    try
    {
    // Create Command
    OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
    MyCmd.Parameters.Add("@unitprice", OleDbType.Double).Value = unitprice;
    MyCmd.Parameters.Add("@productid", OleDbType.BigInt).Value = productid;

    MyCnn.Open();
    MyCmd.ExecuteNonQuery();
    }
    catch (Exception err)
    {
    throw err;
    }
    finally
    {
    MyCnn.Close();
    }

    }

    //Make the Delete
    public void Delete()
    {
    strSql = "DELETE From Products WHERE ProductID=@productid";
    // Create Connection
    OleDbConnection MyCnn = new OleDbConnection(strCon);
    MyCnn.Open();
    // Create Command
    OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
    MyCmd.Parameters.Add("@productid", OleDbType.Integer).Value = productid;
    MyCmd.ExecuteNonQuery();
    MyCnn.Close();
    }
    }
    }

    Στο UI στην ASPX σελίδα χρησιμοποίησα το γνωστό Data-Bound Control GridView για την εμφάνιση/διαχείριση των data, καθορίζοντας στα κατάλληλα events τις αντίστοιχες ρουτίνες στο code-behind file (.apsx.cs):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    <asp:GridView ID="GrdEditProducts" runat="server"
                          CssClass="Gridview"
                          AlternatingRowStyle-CssClass="Alt"
                          DataKeyNames="ProductID, CategoryID, SupplierID"
                          AutoGenerateColumns="false"
                          Showfooter="True"
                          AllowPaging="True"
                          PageSize="10"
                          OnPageIndexChanging="GrdEditProducts_PageIndexChanging" 
                          OnRowCommand="GrdEditProducts_RowCommand" 
                          OnRowDatabound="GrdEditProducts_RowDataBound" 
                          OnRowDeleting="GrdEditProducts_RowDeleting" 
                          OnRowCancelingedit="GrdEditProducts_RowCancelingEdit" 
                          OnRowEditing="GrdEditProducts_RowEditing" 
                          OnRowUpdating="GrdEditProducts_RowUpdating">
                 <Columns>
                          <asp:TemplateField 
                               Visible="false">
                               <ItemTemplate>
                                    <%# Eval("ProductId") %>
                               </ItemTemplate>
                          </asp:TemplateField>
                          <asp:TemplateField 
                               Visible="false">
                               <ItemTemplate>
                                    <%# Eval("CategoryId") %>
                               </ItemTemplate>
                          </asp:TemplateField>
                          <asp:TemplateField 
                               Visible="false">
                               <ItemTemplate>
                                    <%# Eval("SupplierId") %>
                               </ItemTemplate>
                          </asp:TemplateField>
                          <asp:TemplateField 
                                HeaderText="Product Name"
                                itemstyle-horizontalalign="Left">    
                               <ItemTemplate>
                                    </asp:Label ID="lblProductName" runat="server" Text='<%# Eval("ProductName") %>'>
                               </ItemTemplate>
                               <EditItemTemplate>
                                    </asp:TextBox ID="txtProductName" runat="server" Text='<%# Bind("ProductName") %>'>
                                    <asp:RequiredFieldValidator ID="Rfd1" runat="server" 
                                         ControlToValidate="txtProductName"
                                         SetFocusOnError="true"
                                         Display="None"
                                         ErrorMessage="Product Name: You must provide the Name">
                                    </asp:RequiredFieldValidator>
                               </EditItemTemplate>
                               <FooterTemplate>
                                    </asp:TextBox ID="txtProductNameNew" runat="server"> 
                               </FooterTemplate>
                          </asp:TemplateField>
                          ....................
                                   <asp:Button ID="btnEdit" Text="Edit" CommandName="Edit" Runat="Server" Font-Size="7pt" />
                                   <asp:Button ID="btnDelete" Text="Delete" CommandName="Delete"  OnClientClick="return confirm('Are you sure you want to delete this distribution?');" Runat="Server" Font-Size="7pt"/>
                                </ItemTemplate>
                                <EditItemTemplate>
                                   <asp:Button ID="btnUpdate" Text="Update" CommandName="Update" Runat="Server" Font-Size="7pt"/>
                                   <asp:Button ID="btnCancel" Text="Cancel" CommandName="Cancel" Runat="Server" Font-Size="7pt"/>
                                </EditItemTemplate>
                                <FooterTemplate>
                                   <asp:Button ID="btnAddNew" Text="AddNew" CommandName="AddNew" Runat="Server" Font-Size="7pt"/>
                                </FooterTemplate>
                            </asp:TemplateField>
                 </Columns>
            </asp:GridView>

    Ενδεικτικά στο code-behind της συγκεκριμένης σελίδας, δηλώνονταν το object της class και τα κατάλληλα events handlers.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
        public partial class WebForm3 : System.Web.UI.Page
        {
            ClsBindControls BindControls = new ClsBindControls();
            ClsProducts Products = new ClsProducts();
    
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!Page.IsPostBack)
                {
                    // Populate the DropDownList 
                    BindControls.SetDropDownList(DdlCategory, "Categories", "CategoryName", "CategoryID", true, "All Categories", -1);
                    // Populate the GridView
                    BindControls.SetGridView(GrdEditProducts, Products.SetSqlQuery(Convert.ToInt32(DdlCategory.SelectedItem.Value)));
                }
            }
     protected void GrdEditProducts_RowCommand(object sender, GridViewCommandEventArgs e)
            {
                if (e.CommandName.Equals("AddNew"))
                {
                    if (Page.IsValid == false) return;
    
                    TextBox TxtProductName = (TextBox)GrdEditProducts.FooterRow.FindControl("txtProductNameNew");
                    DropDownList DdlCategory = (DropDownList)GrdEditProducts.FooterRow.FindControl("ddlCategoryNew");
                    DropDownList DdlSupplier = (DropDownList)GrdEditProducts.FooterRow.FindControl("ddlSupplierNew");
                    TextBox TxtUnitPrice = (TextBox)GrdEditProducts.FooterRow.FindControl("txtUnitPriceNew");
                    TextBox TxtQuantity = (TextBox)GrdEditProducts.FooterRow.FindControl("txtQuantityNew");
                    
                    Products.ProductName = TxtProductName.Text;
                    Products.CategoryID = Convert.ToInt32(DdlCategory.SelectedItem.Value);
                    Products.SupplierID = Convert.ToInt32(DdlSupplier.SelectedItem.Value);
                    Products.UnitPrice = float.Parse(TxtUnitPrice.Text);
                    Products.Quantity = Convert.ToInt16(TxtQuantity.Text);
                    
                    Products.Insert();
                    BindControls.SetGridView(GrdEditProducts, Products.SetSqlQuery(Convert.ToInt32(DdlCategory.SelectedItem.Value)));
                } 
            }
    
    
            protected void GrdEditProducts_RowEditing(object sender, GridViewEditEventArgs e)
            {
                GrdEditProducts.EditIndex = e.NewEditIndex;
                BindControls.SetGridView(GrdEditProducts, Products.SetSqlQuery(Convert.ToInt32(DdlCategory.SelectedItem.Value)));
            }

    Η συγκεκριμένη υλοποίηση είχε αρκετά αρνητικά σημεία, ειδικά στον ορισμό όλων των events στο code-behind file.

    2)   Χρήση του ObjectDataSource μεταξύ τα Data-Source(database) και του Data-Bound Control(GridView)
    Αρχικά χρησιμοποιήθηκε εκ νέου μια κλάση για τον ορισμό των ενεργειών προς της βάση δεδομένων.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
     
    public class Methods
        {
            private string strSql;
            private string strCon;
            
            // TODO: Add constructor logic here
            public Methods()
    	    {
                strCon = MasterDataJQuery.ClsWebConfig.GetConnectionString();
    	    }
    
            public DataSet GetCategories()
            {
                strSql = "SELECT CategoryID, CategoryName FROM Categories ORDER BY CategoryName";
                OleDbDataAdapter da = new OleDbDataAdapter(strSql, strCon);
                DataSet ds = new DataSet();
                da.Fill(ds);
                return ds;
            }
    
            public DataSet GetSuppliers()
            {
                strSql = "SELECT SupplierID, CompanyName FROM Suppliers ORDER BY CompanyName";
                OleDbDataAdapter MyDa = new OleDbDataAdapter(strSql, strCon);
                DataSet MyDs = new DataSet();
                MyDa.Fill(MyDs);
                return MyDs;
            }
    
            public DataSet GetProductDetail(long ProductID)
            {
                strSql = "SELECT ProductID, Products.CategoryID as CategoryID, Products.SupplierID as SupplierID, ProductName, CategoryName, CompanyName, UnitPrice, UnitsInStock as Quantity ";
                strSql += "FROM Categories INNER JOIN (Suppliers INNER JOIN Products ON Suppliers.SupplierID = Products.SupplierID) ON Categories.CategoryID = Products.CategoryID ";
                strSql += "WHERE ProductID=@ProductID ";
    
                // Create Connection
                OleDbConnection MyCnn = new OleDbConnection(strCon);
                // Create Command
                OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
                // Create DataAdapter
                OleDbDataAdapter MyDa = new OleDbDataAdapter();
                MyDa.SelectCommand = MyCmd;
                // Define Parameteres
                MyCmd.Parameters.Add("@ProductID", OleDbType.BigInt).Value = ProductID;
                // Create & Fill DataSet
                DataSet MyDs = new DataSet();
                MyDa.Fill(MyDs);
                return MyDs;
            }
    
            public DataSet GetProductsByCategory(long CategoryID)
            {
                strSql = "SELECT ProductID, Products.CategoryID as CategoryID, ProductName, CategoryName, UnitPrice, UnitsInStock as Quantity ";
                strSql += "FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID ";
                if (CategoryID != -1)
                   {
                       strSql += "WHERE Products.CategoryID=@CategoryID ";
                   }
                strSql += "ORDER by CategoryName,ProductName ";
    
                // Create Connection
                OleDbConnection MyCnn = new OleDbConnection(strCon);
                // Create Command
                OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
                // Create DataAdapter
                OleDbDataAdapter MyDa = new OleDbDataAdapter();
                MyDa.SelectCommand = MyCmd;
                // Define Parameteres
                // MyCmd.Parameters.AddWithValue("@CategoryID", ProductProperties.CategoryID.ToString());
                MyCmd.Parameters.Add("@CategoryID", OleDbType.BigInt).Value = CategoryID;
                // Create & Fill DataSet
                DataSet MyDs = new DataSet();
                MyDa.Fill(MyDs);
                return MyDs;
            }
    
            public void Update(Properties ProductPrperties)
            {
                strSql =  "UPDATE Products ";
                strSql += "SET ProductName=@ProductName, SupplierID=@SupplierID, CategoryID=@CategoryID, ";
                strSql += "UnitPrice=@UnitPrice, UnitsInStock=@Quantity ";
                strSql += "WHERE ProductID=@ProductID";
                // Create Connection
                OleDbConnection MyCnn = new OleDbConnection(strCon);
                try
                {
                    // Create Command
                    OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
                    
                    MyCmd.Parameters.AddWithValue("@ProductName", ProductPrperties.ProductName);
                    MyCmd.Parameters.AddWithValue("@SupplierID", ProductPrperties.SupplierID);
                    MyCmd.Parameters.AddWithValue("@CategoryID", ProductPrperties.CategoryID);
                    //MyCmd.Parameters.Add("@UnitPrice",OleDbType.Currency).Value = ProductPrperties1.UnitPrice;
                    MyCmd.Parameters.AddWithValue("@UnitPrice", Convert.ToDecimal(ProductPrperties.UnitPrice));
                    MyCmd.Parameters.AddWithValue("@Quantity", ProductPrperties.Quantity);
                    MyCmd.Parameters.AddWithValue("@ProductID", ProductPrperties.ProductID);
    
                    MyCnn.Open();
                    MyCmd.ExecuteNonQuery();
                }
                catch (Exception err)
                {
                    throw err;
                }
                finally
                {
                    MyCnn.Close();
                }
            }
    
            public void Delete(Properties ProductPrperties)
            {
                strSql = "DELETE From Products WHERE ProductID=@productid";
                // Create Connection
                OleDbConnection MyCnn = new OleDbConnection(strCon);
                MyCnn.Open();
                // Create Command
                OleDbCommand MyCmd = new OleDbCommand(strSql, MyCnn);
                MyCmd.Parameters.AddWithValue("@ProductID", ProductPrperties.ProductID);
                MyCmd.ExecuteNonQuery();
                MyCnn.Close();
            }
    
        }
    
    
        public class Properties
        {
            public long ProductID { get; set; }
            public string ProductName { get; set; }
            public long SupplierID { get; set; }
            public long CategoryID { get; set; }
            public decimal UnitPrice { get; set; }
            public long Quantity { get; set; }
        }
    }

    Με βάση την παραπάνω κλάση ορίστηκαν στο ObjectDataSource οι αντίστοιχες ρουτίνες για τις γνωστές ενέργειες (select, insert, update, delete).
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    <%--ODS for DetailsView--%>
            <asp:ObjectDataSource ID="OdsProductDetail" runat="server"
                 DataObjectTypeName="Product.Properties"
                 TypeName="Product.Methods"
                 OldValuesParameterFormatString="{0}"
                 UpdateMethod="Update"
                 DeleteMethod="Delete"
                 SelectMethod="GetProductDetail" 
                 OnSelecting="OdsProductDetail_Selecting">
            </asp:ObjectDataSource>
    <%--GridView--%>
            <asp:GridView ID="GrdProduct" runat="server"
                 CssClass="Gridview"
                 AlternatingRowStyle-CssClass="Alt"
                 DataSourceID="OdsProductList"
                 DataKeyNames="ProductID"
                 AutoGenerateColumns="false"
                 OnSelectedIndexchanged="GrdProduct_SelectedIndexChanged">
                 <Columns>
                          <asp:BoundField DataField="ProductID" Visible="false"/>
                          <asp:BoundField DataField="GategoryID"  Visible="false"/>
                          <asp:BoundField DataField="ProductName" 
                               HeaderText="Product Name" 
                               ItemStyle-HorizontalAlign="Left"/>
                          <asp:BoundField DataField="CategoryName" 
                               HeaderText="Category Name" 
                               ItemStyle-HorizontalAlign="Left"/>
                          <asp:BoundField DataField="UnitPrice" 
                               HeaderText="Unit Price" 
                               ItemStyle-HorizontalAlign="Right"
                               DataFormatString="{0:c1}"/>
                          <asp:TemplateField
                               HeaderText=""
                               FooterStyle-BackColor="#E0E0E0">
                               <ItemTemplate>
                                    <asp:Button ID="btnDetails" Runat="Server" 
                                         Text="Details" 
                                         CommandName="Select" 
                                         Font-Size="7pt" />  
                               </ItemTemplate>
                          </asp:TemplateField> 
                 </Columns>
            </asp:GridView>

    Σημαντικό πλεονέκτημα στην παρούσα υλοποίηση η μη χρηση κώδικα στο code-behind file για τον καθοριμό των αντίστοιχων events handlers, καθως όλη την δουλεια αυτήν την αναλαμβάνει από μόνο του το ODS.

    3) Χρήση JQuery με Ajax-call, όπου καλλώ ασύχρονα από τον client τις αντίστοιχες ρουτίνες που έχω στο object της κλάσης clProdutcs.cs μέσω WebService (.asmx) ή απευθείας με PageMethod από τη aspx σελίδα.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
     <script type="text/javascript">
             $(function () {
             function GetAllCategories() {
                      var ddlCategory = $('#DdlCategories');
                      $.ajax({
                            type: "POST",
                            contentType: "application/json; charset=utf-8",
                            url: "WSProducts.asmx/GetAllGategories",
                            data: "{}",
                            dataType: "json",
                            success: function (response) {
                                    var Categories = jQuery.parseJSON(response.d);
                                    $.each(Categories.Table, function (index, Category) {
                                        ddlCategory.append('<option value="' + Category.CategoryID + '">' + Category.CategoryName + '</option>');
                                    });
                            },
                            error: function (msg) {
                                alert("Error");
                            }
                        });
             
             }
         </script>    


    Θα με ενδιέφερε να γινόνταν αναφορά και σε άλλες εναλλακτικές υλοποίησεις, που ενδεχομένως  εκτελούν με καλύτερο τρόπο την επικοινωνία με την βάση δεδομένων για WebForms (ίσως για MVC θα υπάρχουν άλλες προτεινόμενες υλοποιήσεις)
    .
    Προσωπικά αποτερος στόχος η δυνατότητα δημιουργίας ενός reusable component (.dll) που θα μπορώ να το χρησιμοποιώ με reference  σε οποιοδήποτε project που έχει επικοινωνία με βάση δεδομένων και με ελάχιστο κώδικα να υλοποιώ άμεσα τις βασικές GRUD (Create, Retrieve, Update, Delete) λειτουργίες.
     

  •  12-04-2012, 16:03 69995 σε απάντηση της 69994

    Απ: Best Practise για GRUD operation

    Αν χρησιμοποιήσεις ένα ώριμο OR Mapper (NHibernate, Entity Framework) γλυτώνεις εντελώς τη δημιουργία του CRUD κώδικα. Αν χρησιμοποιήσεις μετά τις δυνατότητες templating και scaffolding που σου παρέχουν διάφορα frameworks αλλά και αυτά τα ίδια τα built-in ASP.NET controls γλυτώνεις και όλο τον επαναλαμβανόμενο κώδικα στο UI. Μάλιστα το Dynamic Data στο ASP.NET και η αντίστοιχη δυνατότητα στο MVC σου επιτρέπουν να δημιουργήσεις πολύ εύκολα UI από ένα entity model που έχει δημιουργηθεί με Entity Framework ή NHibernate
    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  12-04-2012, 16:37 69996 σε απάντηση της 69995

    Απ: Best Practise για GRUD operation

    Θα συμφωνήσω με τον Παναγιώτη ότι η χρήση ORM βοηθούν στην δημιουργία CRUD κώδικα πράγμα που σημαίνει ότι γλυτώνεις τον κόπο και τον χρόνο για να τα υλοποιήσεις.

    Aν θέλαμε να προχωρήσουμε λίγο την σκέψη σου και να δούμε καλύτερα αυτό που ονομάζουμε code reuse μπορούμε να πούμε ότι σε όλες τις εφαρμογές θέλουμε λίγο πολύ να κάνουμε τα ίδια πράγματα

    • data access
    • exception handling
    • logging
    • caching


    Μπορείς π.χ να χρησιμοποιήσεις το Enterprise Library που είναι στην ουσία reusable components τα οποία έχουν υλοποιηθεί από την ομάδα της Microsoft (Patterns & Practices Team)  και μπορείς να τα χρησιμοποιήσεις σε οποιοδήποτε εφαρμογή, μικρή ή enterprise.

    Πρόκειται για μια Open source λύση που στην ουσία μας αποτρέπει να ανακαλύπτουμε τον τροχό.Για τις λύσεις CRUD που θέλεις μπορείς να χρησιμοποιήσεις το Enterprise Library Data Access Block. Δεν είναι ORM αλλά μοιάζει στην υλοποίηση με ADO.Net.


    Νικόλαος Καντζέλης
    BSc, MSc, MCAS, MCPD, MCITP, MCTS,MCP, MCT
    http://www.nksolutions.gr
    http://dotnetstories.wordpress.com
    http://weblogs.asp.net/dotnetstories
    http://forum.dotnetnuke.gr
  •  12-04-2012, 17:31 69999 σε απάντηση της 69996

    Απ: Best Practise για GRUD operation

    Νίκο, το Data Access Block έχει ουσιαστικά εγκαταλειφθεί εδώ και καιρό, από τη στιγμή που υπάρχουν ORMs - πέρα από το ότι πολλά από τα πράγματα που έκανε, τώρα τα κάνει το ίδιο το ADO.NET. Άσε που αν θέλεις να εκτελέσεις εύκολα CRUD εντολές υπάρχουν τα Micro ORMs όπως το Dapper που μετατρέπουν όλη τη διαδικασία του query και φορτώματος σε ένα αντικείμενο, σε μία κυριολεκτικά γραμμή χωρίς mapping.

    Όσον αφορά το code reuse γενικότερα, το ότι υπάρχουν έτοιμες βιβλιοθήκες για διάφορα θέματα είναι δεδομένο - και όχι μόνο για αυτά που αναφέρεις. Μάλιστα το Enterprise Library δεν είναι ούτε η καλύτερη ούτε η απλούστερη λύση για τα θέματα που αναφέρεις. Σύγκρινε για παράδειγμα το log4net με το Logging application block ή το MEF με το Unity. Σε κάθε περίπτωση το block του Ent Lib χάνει.

    Θα έλεγα μάλιστα ότι είναι τελικά κακή ιδέα να χώσεις κάπου το Enterprise Libary χωρίς να δεις ποιές άλλες βιβλιοθήκες υπάρχουν.



    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  12-04-2012, 20:35 70001 σε απάντηση της 69995

    Απ: Best Practise για GRUD operation

    Παναγιώτης Καναβός:
    Αν χρησιμοποιήσεις ένα ώριμο OR Mapper (NHibernate, Entity Framework) γλυτώνεις εντελώς τη δημιουργία του CRUD κώδικα. Αν χρησιμοποιήσεις μετά τις δυνατότητες templating και scaffolding που σου παρέχουν διάφορα frameworks αλλά και αυτά τα ίδια τα built-in ASP.NET controls γλυτώνεις και όλο τον επαναλαμβανόμενο κώδικα στο UI. Μάλιστα το Dynamic Data στο ASP.NET και η αντίστοιχη δυνατότητα στο MVC σου επιτρέπουν να δημιουργήσεις πολύ εύκολα UI από ένα entity model που έχει δημιουργηθεί με Entity Framework ή NHibernate

    Παναγιώτη για web application με web forms έχεις να μας δώσεις κάποιο αντιπροσωπευτικο link για την υλοποίηση που αναφέρεις με το Entity Framework ή NHibernate.
    Θεωρεις πλέον ότι πρέπει να χρησιμοποιούμε αυτές τις τεχνικές για το CRUD κώδικα;
    Επίσης θεωρείς σωστή την προσσέγιση να καλούνται όλα αυτά τα GRUD operation (ανεξάρτητα με τον τρόπο που υλοποιούνται) μέσω Ajax Call και όχι με τον κλασικο τρόπο;
  •  12-04-2012, 21:02 70002 σε απάντηση της 70001

    Απ: Best Practise για GRUD operation

    Αν θες νας δεις μια μικρή εφαρμογή (asp.net web forms) που είχε αναπτυχθεί σαν sample application στο asp.net website ,πάτα εδώ ,

    Μπορείς να κατεβάσεις το project αυτό τοπικά και να δεις πως υλοποιούνται τα CRUD operations. Χρησιμοποιεί το Database First model.

    Νικόλαος Καντζέλης
    BSc, MSc, MCAS, MCPD, MCITP, MCTS,MCP, MCT
    http://www.nksolutions.gr
    http://dotnetstories.wordpress.com
    http://weblogs.asp.net/dotnetstories
    http://forum.dotnetnuke.gr
  •  12-04-2012, 21:11 70003 σε απάντηση της 69999

    Απ: Best Practise για GRUD operation

    θα δω αυτά που μου προτείνεις.Oμολογώ ότι δεν τα έχω δει και δεν μπορώ να κάνω σύγκριση.Εκτιμώ ότι είναι έτσι όπως τα λες.  Πλέον χρησιμοποιώ το EF αρκετά ειδικά τώρα που έχει ωριμάσει σαν framework και υποστηρίζει όλα τα data types καθώς και το Code First Approach.

    Έχω κάνει τα τελευταία 2-3 χρόνια projects χρησιμοποιώντας το Enterprise Library και γενικά μου έλυσε τα χέρια.Θα δω το log4net για ένα νέο project που έχω.

    Νικόλαος Καντζέλης
    BSc, MSc, MCAS, MCPD, MCITP, MCTS,MCP, MCT
    http://www.nksolutions.gr
    http://dotnetstories.wordpress.com
    http://weblogs.asp.net/dotnetstories
    http://forum.dotnetnuke.gr
  •  12-04-2012, 21:44 70004 σε απάντηση της 70003

    Απ: Best Practise για GRUD operation

    Ανοίξαμε μεγάλο θέμα. Προσωπικά, θέλω να έχω τον έλεγχο πάνω στα T-SQL scripts. Το μεγαλύτερο πρόβλημα για μένα είναι το "βάθος" του inheritance. Η υλοποίηση με views για τα selects και stored procedures για updates, inserts και deletes ταιριάζει περισσότερο στην "ιδιοσυγκρασία" μου. Συνεχίζω να θεωρώ τα datasets ως το καλύτερο κομμάτι του ADO.NET μέχρι σήμερα. Υπάρχουν πολλοί τομείς πάνω στους οποίους η Microsoft θα μπορούσε να τα βελτιώσει. Για παράδειγμα, η παρούσα υλοποίηση περιέχει πολύ presentation κώδικα που είναι περιττός στον server. Θα μπορούσαμε να έχουμε ένα lite datatable object για τον server και το γνωστό datatable για τον client. Έχω σκεφτεί κι άλλα πολλά, αλλά η Microsoft τα έχει εγκαταλείψει...

    Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!
  •  14-04-2012, 20:09 70016 σε απάντηση της 69995

    Απ: Εntitydatasource vs Objectdatasource

    Παναγιώτης Καναβός:
    Αν χρησιμοποιήσεις ένα ώριμο OR Mapper (NHibernate, Entity Framework) γλυτώνεις εντελώς τη δημιουργία του CRUD κώδικα. Αν χρησιμοποιήσεις μετά τις δυνατότητες templating και scaffolding που σου παρέχουν διάφορα frameworks αλλά και αυτά τα ίδια τα built-in ASP.NET controls γλυτώνεις και όλο τον επαναλαμβανόμενο κώδικα στο UI. Μάλιστα το Dynamic Data στο ASP.NET και η αντίστοιχη δυνατότητα στο MVC σου επιτρέπουν να δημιουργήσεις πολύ εύκολα UI από ένα entity model που έχει δημιουργηθεί με Entity Framework ή NHibernate


    Ανάμεσα στις δυο υλοποιήσεις  (Εntitydatasource ή Objectdatasource) για το DAL, ποία χρησιμοποιείται πλέον περισσότερο;
    Από ότι έχω καταλάβει με το  Εntitydatasource γλιτώνεις το όλο κομμάτι του CRUD κώδικα, αλλά δεν γνωρίζω με ποιο ενδεχομένως trade-off συγκριτικά με το Objectdatasource.
    Προς το παρον στο πλαίσο των Web-Forms προσπαθώ να διαπιστώσω τα pros&cons σχετικά με το  Εntitydatasource vs Objectdatasource.
    Για την υλοποίηση Web Apps μέσω MVC στο θέμα του DAL υφίστανται ξανά οι ίδιοι προβληματισμοί ή έχουν πιο ξεκάθαρα patterns για την εκτέλεση του DAL; 
  •  14-04-2012, 21:19 70017 σε απάντηση της 70016

    Απ: Εntitydatasource vs Objectdatasource




    Με το EntityDataSource μπορείς να υλοποιήσεις πολύ γρήγορα την web forms εφαρμογή σου. Στην ουσία γράφεις όλο το Business logic & data access logic στις .aspx σελίδες σου...Όπως καταλαβαίνεις δεν υπάρχει καθόλου code reuse....Εϊναι λύση για πολύ μικρές εφαρμογές σχετικά απλές που δεν θα "μεγαλώσουν" πολύ στο μέλλον...Με τον τρόπο αυτό δεν γράφεις τον κώδικα σε layers/tiers.Ένας τρόπος να γράψεις τον κώδικα σου με καλύτερο τρόπο είναι αντί για το EntityDataSource control να χρησιμοποιήσεις το ObjectDataSource control.Με τον τρόπο αυτό γράφεις εσύ τον κώδικα για το DAL. Γράφεις τον κώδικα για το select,insert,update,delete αλλά μπορείς (επειδή γράφεις εσύ τον κώδικα) να γράψεις στην delete() μέθοδο ότι κώδικα θέλεις π.χ όταν κάνεις delete ένα row αυτό να πάει σε ένα άλλο Archive πίνακα. 

    Αν θες να δεις ένα blog post μου που υλοποιώ μια απλή εφαρμογή με LINQ to SQL & το ObjectDataSource control δες εδώ . Εδώ μπορείς να δεις ένα blog post μου πως χρησιμοποιήσεις το  EntityDataSource control.

    Αν θες να δεις πως χειριζόμαστε CRUD operations στις ASP.Νet MVC applications , σου συνιστώ ανεπιφύλακτα να δεις αυτά εδώ τα tutorials.  

    To MVC pattern υλοποιεί εκ φύσεως πολύ καλύτερα αυτό που λέμε seperation of concerns. Αν θες να δεις ένα απλό παράδειγμα δες εδώ .

    Νικόλαος Καντζέλης
    BSc, MSc, MCAS, MCPD, MCITP, MCTS,MCP, MCT
    http://www.nksolutions.gr
    http://dotnetstories.wordpress.com
    http://weblogs.asp.net/dotnetstories
    http://forum.dotnetnuke.gr
  •  17-04-2012, 10:36 70029 σε απάντηση της 70017

    Απ: Εntitydatasource vs Objectdatasource

    Η σύγκριση είναι λάθος, καθώς το Entity Framework (ή οποιοδήποτε άλλο ORM) δεν απαιτεί τη χρήση κανενός είδους "xxxDataSource".  Ουσιαστικά τα datasources είναι ένα anti-pattern (δηλ. πάρα πολύ κακή συνήθεια) η οποία προσπαθεί να περάσει στο χώρο του object-oriented programming τεχνικές που είχαν εφαρμογή μόνο στις εφαρμογές data entry της προ-προηγούμενης δεκατετίας (1990s). 
        Τότε κύρια ανησυχία ήταν πως θα φτιάξεις πιο γρήγορα κάποιες data entry φόρμες.  Τα διάφορα sources διευκολύνανε την επικοινωνία με τη βάση κρύβοντας τον τρόπο και την SQL από προγραμματιστές που δεν ήξεραν SQL. Η κατάσταση βελτιώθηκε αρκετά γρήγορα με το .NET 2.0 και τα διάφορα datasources έχασαν την όποια αξία τους. Άσε που ο κώδικας που παρήγαν οι προγραμματιστές "που δεν ξέραν SQL" δημιουργούσε φοβερά προβλήματα σε όλα τα client-server συστήματα της εποχής και συνεχή κλειδώματα ακόμα και για λίγους χρήστες.
        Αργότερα όμως εμφανίστηκε η ανάγκη να μπορείς να υλοποιήσεις πιο περίπλοκες συμπεριφόρες που αγγίζανε 2-3 διαφορετικές οντότητες (φαντάσου πχ. την ενοικίαση ενός αυτοκινήτου). Επιπλέον, ο αριθμός των χρηστών αυξήθηκε πέρα από τους .... 5 και προφανώς δεν μπορούσε κανείς να ισχυριστεί ότι θα μπορούσε να γράψει φόρμες αγνοώντας την πρόσβαση στη βάση.

    Ακόμα και τότε, τα datasources ήταν αποτυχία και κανείς δεν τα χρησιμοποιούσε σε σοβαρές εφαρμογές.

    Τα διάφορα .NET datasources εμφανίστηκαν στις πρώτες εκδόσεις του .NET για να διευκολύνουν τη γρήγορη δημιουργία φορμών, στο στυλ των sources που χρησιμοποιούσε η VB6. Τω καιρώ εκείνω, το data binding ήταν πολύ πιο δύσκολο και φασαριόζικο. Ουσιαστικά ήταν μία προσπάθεια να κρύψουν την απαιτούμενη SQL, τον ADO.ΝΕΤ κώδικα και το data binding. Εσύ "απλά" θα "σχεδίαζες" το query. Η αποτυχία τους ήταν πλήρης, ακόμα και στην VB6, καθώς για να κάνεις κάτι πέρα από toy εφαρμογή χρειάζεται να ασχοληθείς σοβαρά και με την SQL και με τον κώδικα του data access. Επιπλέον, η ίδια η φιλοσοφία των datasources δημιούργησε προβλήματα, καθώς σε ανάγκαζαν να "χώσεις" θέματα χαμηλού επιπέδου μέσα στο ίδιο το UI.

    Ειδικά  το ObjectDataSource προσπαθούσε να κρύψει την έλλειψη (τότε) κάποιου ORM στο χώρο του .NET, παρέχοντας πρόσβαση σε "Business Objects" τα οποία κρύβαν πίσω τους τον data access κώδικα, αλλά έπρεπε να "βγάζουν" προς τα έξω κάποιες CRUD μεθόδους. Προφανώς δεν έπιασε ούτε αυτό, καθώς τελικά δεν διευκόλυνε σε κάτι. Το μανίκι είναι η λογική και ο data access κώδικας, όχι πως θα καλέσεις τα CRUD! 
    Άσε που σε σχέση με τα ORMs, το ObjectDataSource σε αναγκάζει να "βρωμίσεις" τις κλάσεις σου με κώδικα που δεν έχει θέση σε αυτές.

    Το EntityDataSource είναι μία προσπάθεια να δημιουργηθεί ένα πιο εξελιγμένο ObjectDatasource , πάνω από ένα ORM, το Entity Framework. Επιλέγεις τις οντότητες σου, άντε δίνεις και το LINQ query, και αυτό φτιάχνει τις αντίστοιχες κλήσεις στο ORM. Χονδρικά είναι ένα ObjectDataSource στο οποίο "δεν χρειάζεται" να γράψεις τα CRUD. Άλλη μία αποτυχία γιατί:
    • Τα αντικείμενα ΔΕΝ έχουν σχέση με το CRUD αλλά να παρέχουν μεθόδους ανωτέρου επιπέδου. Φαντάσουν ένα αντικείμενο "Αυτοκίνητο" το οποίο περιέχει μία μέθοδο που λέγεται "Ενοικίαση".
    • Σου πετάει το ORM μέσα στη φόρμα
    • Σε περιορίζει στα queries που μπορείς να κάνεις
    • Σε περιορίζει στο είδος των validation ή άλλων ενεργειών που θέλεις να κάνεις. Άλλο ένα action που λέει "ενοικίαση" και άλλο τα πολλαπλά updates που απαιτούνται σε διάφορες οντότητες για να υλοποιηθεί η ενοικίαση ενός αυτοκινήτου.
    • Ουσιαστικά αντιστρέφει (διαστρέφει θα έλεγα) τη λειτουργία του ORM. Εκεί που κατάφερες να μεταφέρεις αλλού τον data access κώδικα, σου τον ξαναφέρνει στη μούρη!

    Η κατάληξη είναι ότι δεν χρειάζεσαι κανένα datasource. Όλα τα data controls του ASP.NET υποστηρίζουν data binding σε αντικείμενα, οπότε από τη στιγμή που έχεις φορτώσει το αντικείμενο σου, μπορείς να το δείξεις. 




    Νίκο, νομίζω έχεις μπερδέψει τί κάνει το Entity Framework και τί κάνουν τα ObjectDataSource και EntityDataSource.

    Το σίγουρο είναι ότι το EntityDataSource ΔΕΝ αφορά σε καμμία απολύτως περίπτωση το business logic, ούτε έχει να κάνει τίποτε με code reuse. Επίσης, το ObjectDatasource είναι εντελώς περιττό από τη στιγμή που υπάρχει data binding.

    Η κουβέντα για layers και MVC pattern πάντως δεν έχει καμμία απολύτως θέση σε αυτή τη συζήτηση, καθώς αφορά τη σχεδίαση μίας εφαρμογής σε πολύ ανώτερο επίπεδο από το data access. Σα να λέμε όχι μήλα και μηλόπιτα, αλλά μήλα και σπάτουλα ...

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  17-04-2012, 11:12 70032 σε απάντηση της 70029

    Απ: Εntitydatasource vs Objectdatasource

    Παναγιώτης Καναβός:
    Ειδικά  το ObjectDataSource προσπαθούσε να κρύψει την έλλειψη (τότε) κάποιου ORM στο χώρο του .NET, παρέχοντας πρόσβαση σε "Business Objects" τα οποία κρύβαν πίσω τους τον data access κώδικα, αλλά έπρεπε να "βγάζουν" προς τα έξω κάποιες CRUD μεθόδους. Προφανώς δεν έπιασε ούτε αυτό, καθώς τελικά δεν διευκόλυνε σε κάτι. Το μανίκι είναι η λογική και ο data access κώδικας, όχι πως θα καλέσεις τα CRUD! 
    Άσε που σε σχέση με τα ORMs, το ObjectDataSource σε αναγκάζει να "βρωμίσεις" τις κλάσεις σου με κώδικα που δεν έχει θέση σε αυτές.


    Παναγιώτη, μπορείς να το αναπτύξεις αυτό λίγο περισσότερο; Στο ObjectDataSource δεν είναι υποχρεωτικό να δηλώσεις data access κώδικα. Απλά signatures για SelectMethod, UpdateMethod και DeleteMethod. Δεν είναι υποχρεωτικό να υπάρχει κάποιο query μέσα σ' αυτές. Αρκεί να περάσεις τις κατάλληλες παραμέτρους, οι οποίες πρέπει να ταιριάζουν με το sugnature, και κάνεις ό,τι θες, κατευθύνοντας το action εκεί που θες εσύ, χωρίς να χρειάζεται να "αντιγράψεις" τα παραδείγματα του MDSN. Γιατί, λοιπόν, να "βρομίσω" τις κλάσεις μου; Αντίθετα, το Select property του EntityDataSource περιμένει ένα Select statement, οπότε εδώ τα πράγματα είναι διαφορετικά.

    Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!
  •  17-04-2012, 11:42 70034 σε απάντηση της 70032

    Απ: Εntitydatasource vs Objectdatasource

    Αυτά τα CRUD operations δεν "βρωμάνε" σε μία κλάση που σκοπό έχει να παρουσιαστεί στην οθόνη? Στο παράδειγμα της ενοικίασης αυτοκινήτου, τί νόημα θα είχε η UpdateMethod? Τα "απλά" signatures της ObjectDataSource στην πραγματικότητα κρύβουν DAL κώδικα τον οποίο απλά θα πρέπει να γράψεις εσύ, δεν θα στον δημιουργήσει το ίδιο το datasource. 

    Όσο για το  "κάνεις ότι θες" δείχνει το μέγεθος του προβλήματος. Ενώ αυτό που θέλω να κάνω είναι μία ενοικίαση, η οποία κατά προτίμηση θα λέγεται Rent(), αναγκάζομαι να φτιάξω μία update, με ένα μάτσο παραμέτρους που δεν χρειάζομαι, η οποία θα πρέπει να "μαντεύει" ότι σε αυτή τη φόρμα θέλω να κάνω ενοικίαση και ΟΧΙ καταχώρηση νέου αυτοκινήτου. Ενώ θα μπορούσα να καθαρίσω με μία Car.Rent(Customer), θα αναγκαστώ να περάσω πράγματα μόνο και μόνο για να ικανοποιηθεί η UpdateMethod.

    Για σκέψου η ενοικίαση να γίνεται καλώντας ένα web service αντί για update στη βάση. Θα πρέπει να φτιάξω καινούρια φόρμα? Γιατί?

    Και το θέμα είναι ότι τίποτε από αυτά δεν είναι απαραίτητο. Το ObjectDataSource ΔΕΝ μου δίνει κάτι επιπλέον σε σχέση με το απλό data binding και της χρήση του οποιουδήποτε ORM. 

    Disclaimer: Όπως όλοι, κάθε φορά που βγαίνει ένα νέο datasource λέω κι εγώ να το χρησιμοποιήσω και μετά καταριέμαι την ώρα και τη στιγμή. Τελευταία γκάφα ήταν η χρήση του EntityDataSource σε Silverlight πριν κανα χρόνο, για να μιλήσω με WCF Data Services, επειδή βαριόμουν τις ασύγχρονες κλήσεις. Εκεί διαπίστωσα τί πλάκα έχει να συνδέσεις ένα Grid, pager και property grid πάνω σε ένα datasource, το οποίο αποφασίζει ξαφνικά να γυρίσει σε edit mode χωρίς να σου το πει. ΜΠΛΙΑΧ!

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  17-04-2012, 13:30 70037 σε απάντηση της 70034

    Απ: Εntitydatasource vs Objectdatasource

    Αυτή είναι η λογική του ότι τα Update και Delete methods έχουν να κάνουν με τη βάση. Στην ουσία έχουν να κάνουν με το control της φόρμας και τα commands που εκτελούνται εκεί. Θυμάσαι ένα thread που άνοιξε για crosstab editing σε Lightswitch; Δοκίμασα να δω αν μπορεί να γίνει σε ASP.NET (ναι - ναι, με datatables). Βεβαίως και ΔΕΝ χρησιμοποίησα database table με ορθογώνιες διαστάσεις (n x m) γιατί κάτι τέτοιο θα είχε ως αποτέλεσμα το table να μεγαλώνει ανεξέλεγκτα με κάθε νέα εγγραφή, για κάθε μία από τις διαστάσεις του (χώρια του ότι κάθε προσπάθεια "συντήρησης" της "ορθογωνιότητας" θα ήταν σκέτο μελόδραμα). Έφτιαξα, λοιπόν, ένα dummy datatable στο οποίο έκανα το crosstab και το "έδεσα" σ' ένα gridview. Το μόνο action που είχε νόημα πια ήταν το "Update" (για το control). Στη βάση τα πράγματα ήταν διαφορετικά. Αν στο κελί υπήρχε τιμή και αυτή άλλαζε, τότε είχαμε update του record. Αν στο κελί γινόταν διαγραφή τιμής, "εισάγοντας" ένα "κενό" string, τότε στη βάση το συγκεκριμένο record διαγραφόταν. Τέλος, αν σε κενό κελί γινόταν εισαγωγή τιμής, τότε στη βάση είχαμε insert. Το ObjectDataSource συμπεριφέρθηκε άψογα, ανάλογα με τις τιμές των παραμέτρων που περνούσα στην UpdateMethod (DeleteMethod δεν υπήρχε γιατί δεν είχε νόημα). Αυτό που περιγράφω, σε τι διαφέρει από το rent action; Αν κατάλαβα καλά, θέλεις με edit στο grid να κάνεις insert στη βάση (νέο rent). Αυτό είναι κάτι που μπορεί να γίνει.

    Βέβαια, η όλη συζήτηση έχει "ακαδημαϊκό" χαρακτήρα και όχι να πείσει για το αν η χρήση ή η μη χρήση του ObjectDataSource αποτελεί σωστή πρακτική. Δόξα τω θεώ, υπάρχουν πολλές εναλλακτικές προσεγγίσεις για το ίδιο πρόβλημα.

    Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!
  •  17-04-2012, 15:47 70043 σε απάντηση της 70029

    Απ: Εntitydatasource vs Objectdatasource

    Γενικότερα δεν τα χρησιμοποιώ τα datasources για τους λόγους που αναφέρεις.Όπως και να το κάνεις δεν συμφωνούν με τα software patterns.Χρησιμοποιώ το EF χωρίς τα datasources εκτός από ελάχιστα πολύ μικρά Projects....

    Συμφωνώ με αυτό που λες εδώ

    "Το σίγουρο είναι ότι το EntityDataSource ΔΕΝ αφορά σε καμμία απολύτως περίπτωση το business logic, ούτε έχει να κάνει τίποτε με code reuse"

    το ίδιο λέω και εγώ στο δικό μου σχόλιο....


    "Με το EntityDataSource μπορείς να υλοποιήσεις πολύ γρήγορα την web forms εφαρμογή σου. Στην ουσία γράφεις όλο το Business logic & data access logic στις .aspx σελίδες σου...Όπως καταλαβαίνεις δεν υπάρχει καθόλου code reuse..."




    Μάλλον δεν ήμουν αρκετά σαφής. Δεν είναι ο καλύτερος τρόπος να κάνεις code reuse (αν μπορείς να το πεις code reuse) χρησιμοποιώντας το ObjectDataSource. Αλλά π.χ σε αυτό εδώ το blog post μου δείχνω ότι σε σχέση με το EntityDataSource/LinqDataSource μπορώ να "γράψω" ένα καλύτερο """""data access layer""""" με ObjectDatasource

    Π.χ φτιάχνω ένα DAL.cs class file και γράφω π.χ μια μέθοδο

     public List<String> GetCities()
        {
            using (var ctx = new PubsDataContext())
            {
     
                var query = (from auth in ctx.authors
                            select auth.city).Distinct().ToList();
     
                return query;
     
     
     
            }

    και μετά το δένω με το ObjectDataSource την DAL κλάσση και τις μεθόδους της.Αν π.χ κάτι πάει λάθος ξέρω ότι πρέπει να ψάξω στο DAL.cs. είναι ένα καλύτερο ""seperation of concerns"".

    θα μου πεις, που είναι το code reuse? Σε ένα παραπλήσιο project μπορείς να κάνεις copy-paste το DAL.cs και να αλλάξεις π.χ την GetCities Και να την κάνεις GetOrders  και να αλλάξεις τον κώδικα κατάλληλα.

    Δεν είναι βέβαια αυτό ένα γνήσιο code reuse και δεν γίνεται implement με τον τρόπο αυτό....Υπάρχουν ασφαλώς πολύ καλύτεροι τρόποι να το κάνεις. δεν είμαι λοιπόν θιασώτης αυτής της λύσης....απλά μιλούσα για την σύγκριση EntityDataSouce vs ObjectDataSource
     

    Δεν θα  διάλεγα πάντως (data sources) για να κάνω ένα σοβαρό enterprise application.Συμφωνώ ότι το EF δεν τα χρειάζεται και η δουλειά μας γίνεται με databinding.





    Νικόλαος Καντζέλης
    BSc, MSc, MCAS, MCPD, MCITP, MCTS,MCP, MCT
    http://www.nksolutions.gr
    http://dotnetstories.wordpress.com
    http://weblogs.asp.net/dotnetstories
    http://forum.dotnetnuke.gr
Σελίδα 1 από 2 (19 εγγραφές)   1 2 >
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems