Partager via


Mise à jour par lots (C#)

par Scott Mitchell

Télécharger le PDF

Découvrez comment mettre à jour plusieurs enregistrements de base de données en une seule opération. Dans la couche d’interface utilisateur, nous créons un GridView où chaque ligne est modifiable. Dans la couche d’accès aux données, nous encapsulons les plusieurs opérations de mise à jour dans une transaction pour nous assurer que toutes les mises à jour réussissent ou que toutes les mises à jour sont restaurées.

Introduction

Dans le tutoriel précédent , nous avons vu comment étendre la couche d’accès aux données pour ajouter la prise en charge des transactions de base de données. Les transactions de base de données garantissent qu’une série d’instructions de modification des données sera traitée comme une seule opération atomique, ce qui garantit que toutes les modifications échouent ou que toutes réussissent. Cette fonctionnalité DAL de bas niveau étant hors de portée, nous sommes prêts à nous intéresser à la création d’interfaces de modification de données par lots.

Dans ce tutoriel, nous allons créer un GridView où chaque ligne est modifiable (voir figure 1). Étant donné que chaque ligne est rendue dans son interface d’édition, il n’est pas nécessaire d’utiliser une colonne de boutons Modifier, Mettre à jour et Annuler. Au lieu de cela, il existe deux boutons Mettre à jour les produits sur la page qui, lorsqu’on y clique, énumérent les lignes GridView et mettent à jour la base de données.

Chaque ligne du GridView est modifiable

Figure 1 : Chaque ligne du GridView est modifiable (cliquez pour afficher l’image en taille réelle)

Commençons !

Notes

Dans le tutoriel Exécution d’un traitement par lot Mises à jour, nous avons créé une interface d’édition de lot à l’aide du contrôle DataList. Ce didacticiel diffère du précédent dans le sens où utilise un GridView et la mise à jour par lots est effectuée dans l’étendue d’une transaction. Après avoir terminé ce didacticiel, je vous encourage à revenir au tutoriel précédent et à le mettre à jour pour utiliser la fonctionnalité liée aux transactions de base de données ajoutée dans le tutoriel précédent.

Examen des étapes pour rendre toutes les lignes GridView modifiables

Comme indiqué dans le tutoriel Vue d’ensemble de l’insertion, de la mise à jour et de la suppression de données, GridView offre une prise en charge intégrée pour la modification de ses données sous-jacentes par ligne. En interne, gridView note quelle ligne est modifiable via sa EditIndex propriété. Comme gridView est lié à sa source de données, il vérifie chaque ligne pour voir si l’index de la ligne est égal à la valeur de EditIndex. Si c’est le cas, ces champs de ligne sont rendus à l’aide de leurs interfaces de modification. Pour BoundFields, l’interface de modification est une Zone de texte dont Text la propriété est affectée à la valeur du champ de données spécifié par la propriété s DataField de BoundField. Pour TemplateFields, le EditItemTemplate est utilisé à la ItemTemplateplace de .

Rappelez-vous que le workflow de modification démarre lorsqu’un utilisateur clique sur le bouton Modifier d’une ligne. Cela provoque une publication, définit la propriété GridView sur EditIndex l’index s de ligne cliqué et relie les données à la grille. Lorsque vous cliquez sur le bouton Annuler d’une ligne, la publication EditIndex est définie sur une valeur de avant de -1 lier les données à la grille. Étant donné que les lignes de GridView commencent à s’indexer à zéro, la définition EditIndex de sur -1 a pour effet d’afficher gridView en mode lecture seule.

La EditIndex propriété fonctionne bien pour l’édition par ligne, mais n’est pas conçue pour la modification par lots. Pour rendre l’ensemble de GridView modifiable, nous devons rendre chaque ligne à l’aide de son interface d’édition. Le moyen le plus simple d’y parvenir consiste à créer un emplacement où chaque champ modifiable est implémenté en tant que TemplateField avec son interface d’édition définie dans .ItemTemplate

Au cours des étapes suivantes, nous allons créer un GridView entièrement modifiable. À l’étape 1, nous allons commencer par créer le GridView et son ObjectDataSource, puis convertir ses BoundFields et CheckBoxField en TemplateFields. Dans les étapes 2 et 3, nous allons déplacer les interfaces d’édition des TemplateFields EditItemTemplate vers leurs ItemTemplate s.

Étape 1 : Affichage des informations sur le produit

Avant de nous soucier de la création d’un GridView où les lignes sont modifiables, commençons par afficher simplement les informations sur le produit. Ouvrez la BatchUpdate.aspx page dans le BatchData dossier et faites glisser un GridView de la boîte à outils vers le Designer. Définissez gridView sur IDProductsGrid et, à partir de sa balise active, choisissez de le lier à un nouvel ObjetDataSource nommé ProductsDataSource. Configurez ObjectDataSource pour récupérer ses données à partir de la ProductsBLL méthode class s GetProducts .

Configurer objectDataSource pour utiliser la classe ProductsBLL

Figure 2 : Configurer ObjectDataSource pour utiliser la ProductsBLL classe (cliquer pour afficher l’image en taille réelle)

Récupérer les données de produit à l’aide de la méthode GetProducts

Figure 3 : Récupérer les données de produit à l’aide de la GetProducts méthode (cliquer pour afficher l’image en taille réelle)

Comme GridView, les fonctionnalités de modification d’ObjectDataSource sont conçues pour fonctionner sur une base par ligne. Pour mettre à jour un jeu d’enregistrements, nous devons écrire un peu de code dans la classe code-behind de la page ASP.NET qui lote les données et les transmet à la BLL. Par conséquent, définissez les listes déroulantes des onglets UPDATE, INSERT et DELETE d’ObjectDataSource sur (Aucun). Cliquez sur Terminer pour terminer l'Assistant.

Définissez le Drop-Down Listes dans les onglets UPDATE, INSERT et DELETE sur (Aucun)

Figure 4 : Définissez le Drop-Down Listes dans les onglets UPDATE, INSERT et DELETE sur (Aucun) (Cliquez pour afficher l’image en taille réelle)

Une fois l’Assistant Configurer la source de données terminée, le balisage déclaratif d’ObjectDataSource doit ressembler à ce qui suit :

<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>

À l’issue de l’Assistant Configurer la source de données, Visual Studio crée également BoundFields et un CheckBoxField pour les champs de données de produit dans GridView. Pour ce didacticiel, laissez uniquement l’utilisateur afficher et modifier le nom du produit, la catégorie, le prix et les status abandonnés. Supprimez tous les ProductNamechamps sauf les champs , CategoryName, UnitPriceet Discontinued et renommez les HeaderText propriétés des trois premiers champs respectivement Product, Category et Price. Enfin, case activée les cases à cocher Activer la pagination et Activer le tri dans la balise intelligente de GridView.

À ce stade, le GridView a trois BoundFields (ProductName, CategoryNameet UnitPrice) et un CheckBoxField (Discontinued). Nous devons convertir ces quatre champs en TemplateFields, puis déplacer l’interface d’édition des TemplateField s EditItemTemplate vers son ItemTemplate.

Notes

Nous avons exploré la création et la personnalisation de TemplateFields dans le tutoriel Personnalisation de l’interface de modification des données . Nous allons suivre les étapes de conversion de BoundFields et CheckBoxField en TemplateFields et de définition de leurs interfaces de modification dans leurs ItemTemplate s, mais si vous êtes bloqué ou avez besoin d’un actualisation, n’hésitez pas à revenir à ce tutoriel précédent.

Dans la balise active gridView, cliquez sur le lien Modifier les colonnes pour ouvrir la boîte de dialogue Champs. Ensuite, sélectionnez chaque champ et cliquez sur le lien Convertir ce champ en un templateField.

Convertir les champs BoundField et CheckBoxField existants en templateField

Figure 5 : Convertir les champs boundField et CheckBoxField existants en templateField

Maintenant que chaque champ est un TemplateField, nous sommes prêts à déplacer l’interface d’édition du EditItemTemplate s vers le ItemTemplate s.

Étape 2 : création et modification desProductNameUnitPriceDiscontinued interfaces

La création des ProductNameinterfaces , UnitPriceet Discontinued la modification sont la rubrique de cette étape et sont assez simples, car chaque interface est déjà définie dans templateField s EditItemTemplate. La création de l’interface CategoryName d’édition est un peu plus impliquée, car nous devons créer un DropDownList des catégories applicables. Cette CategoryName interface d’édition est abordée à l’étape 3.

Commençons par templateField ProductName . Cliquez sur le lien Modifier les modèles à partir de la balise active GridView, puis accédez à ProductName TemplateField s EditItemTemplate. Sélectionnez textBox, copiez-le dans le Presse-papiers, puis collez-le dans templateField ProductName s ItemTemplate. Remplacez la propriété de TextBox par IDProductName.

Ensuite, ajoutez un RequiredFieldValidator à pour ItemTemplate vous assurer que l’utilisateur fournit une valeur pour chaque nom de produit. Définissez la ControlToValidate propriété sur ProductName, la ErrorMessage propriété sur Vous devez fournir le nom du produit. et la Text propriété à *. Après avoir effectué ces ajouts à , ItemTemplatevotre écran doit ressembler à la figure 6.

ProductName TemplateField inclut désormais une Zone de texte et un RequiredFieldValidator

Figure 6 : Le ProductName TemplateField inclut désormais une zone de texte et un requiredFieldValidator (cliquez pour afficher l’image de taille réelle)

Pour l’interface UnitPrice d’édition, commencez par copier la zone de texte du EditItemTemplate vers le ItemTemplate. Ensuite, placez un $ devant textBox et définissez sa ID propriété sur UnitPrice et sa Columns propriété sur 8 .

Ajoutez également un CompareValidator aux UnitPrice s ItemTemplate pour vous assurer que la valeur entrée par l’utilisateur est une valeur monétaire valide supérieure ou égale à 0,00 $. Définissez la propriété s du ControlToValidate validateur sur UnitPrice, sa ErrorMessage propriété sur Vous devez entrer une valeur monétaire valide. Omettez tous les symboles monétaires., sa Text propriété sur *, sa Type propriété Currencysur , sa Operator propriété sur GreaterThanEqualet sa ValueToCompare propriété sur 0 .

Ajouter un compareValidator pour vérifier que le prix entré est une valeur monétaire non négative

Figure 7 : Ajouter un compareValidator pour vérifier que le prix entré est une valeur monétaire non négative (cliquez pour afficher l’image en taille réelle)

Pour templateFieldDiscontinued, vous pouvez utiliser la Case à cocher déjà définie dans .ItemTemplate Définissez simplement son ID sur Discontinued et sa Enabled propriété sur true.

Étape 3 : Création de l’interface d’éditionCategoryName

L’interface de modification dans templateField CategoryName s EditItemTemplate contient une zone de texte qui affiche la valeur du champ de CategoryName données. Nous devons le remplacer par une liste déroulante qui répertorie les catégories possibles.

Notes

Le tutoriel Personnalisation de l’interface de modification des données contient une discussion plus approfondie et complète sur la personnalisation d’un modèle afin d’inclure un DropDownList plutôt qu’une zone de texte. Bien que les étapes soient terminées, elles sont présentées de manière terse. Pour plus d’informations sur la création et la configuration des catégories DropDownList, reportez-vous au didacticiel Personnalisation de l’interface de modification de données .

Faites glisser un DropDownList de la boîte à outils sur templateField CategoryName , ItemTemplateen définissant sa ID sur Categories. À ce stade, nous définissons généralement la source de données de DropDownLists par le biais de sa balise active, en créant un objet ObjectDataSource. Toutefois, cette opération ajoute l’ObjectDataSource dans , ItemTemplatece qui entraîne la création d’un instance ObjectDataSource pour chaque ligne GridView. Au lieu de cela, nous allons créer l’ObjetDataSource en dehors des TemplateFields de GridView. Terminez la modification du modèle et faites glisser un ObjetDataSource de la boîte à outils vers le Designer sous ObjectDataSourceProductsDataSource. Nommez le nouvel ObjetDataSource CategoriesDataSource et configurez-le pour utiliser la CategoriesBLL méthode class s GetCategories .

Configurer ObjectDataSource pour utiliser la classe CategoriesBLL

Figure 8 : Configurer ObjectDataSource pour utiliser la CategoriesBLL classe (cliquer pour afficher l’image en taille réelle)

Récupérer les données category à l’aide de la méthode GetCategories

Figure 9 : Récupérer les données de catégorie à l’aide de la GetCategories méthode (Cliquer pour afficher l’image en taille réelle)

Étant donné que cet ObjetDataSource est utilisé uniquement pour récupérer des données, définissez les listes déroulantes dans les onglets UPDATE et DELETE sur (Aucun). Cliquez sur Terminer pour terminer l'Assistant.

Définissez le Drop-Down Listes dans les onglets UPDATE et DELETE sur (Aucun)

Figure 10 : Définissez le Drop-Down Listes dans les onglets UPDATE et DELETE sur (Aucun) (Cliquez pour afficher l’image en taille réelle)

Une fois l’Assistant terminé, le CategoriesDataSource balisage déclaratif s doit se présenter comme suit :

<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

Une fois le CategoriesDataSource créé et configuré, revenez à TemplateField CategoryName et ItemTemplate , à partir de la balise active de DropDownList, cliquez sur le lien Choisir une source de données. Dans l’Assistant Configuration de la source de données, sélectionnez l’option CategoriesDataSource dans la première liste déroulante et choisissez d’avoir CategoryName utilisé pour l’affichage et CategoryID comme valeur.

Lier le DropDownList à CategoriesDataSource

Figure 11 : Lier la liste déroulante à (CategoriesDataSourceCliquer pour afficher l’image en taille réelle)

À ce stade, le Categories DropDownList répertorie toutes les catégories, mais il ne sélectionne pas encore automatiquement la catégorie appropriée pour le produit lié à la ligne GridView. Pour ce faire, nous devons définir dropDownList Categories sur SelectedValue la valeur du CategoryID produit. Cliquez sur le lien Modifier dataBindings à partir de la balise active de DropDownList et associez la SelectedValue propriété au champ de données, comme illustré dans la CategoryID figure 12.

Lier la valeur CategoryID du produit à la propriété SelectedValue de DropDownList

Figure 12 : Lier la valeur du CategoryID produit à la propriété dropDownList SelectedValue

Un dernier problème demeure : si le produit n’a pas de CategoryID valeur spécifiée, l’instruction de liaison de données sur SelectedValue génère une exception. En effet, dropDownList contient uniquement des éléments pour les catégories et n’offre pas d’option pour les produits qui ont une NULL valeur de base de données pour CategoryID. Pour résoudre ce problème, définissez la propriété true de AppendDataBoundItems DropDownList sur et ajoutez un nouvel élément à la liste DropDownList, en omettant la Value propriété de la syntaxe déclarative. Autrement dit, assurez-vous que la Categories syntaxe déclarative de DropDownList se présente comme suit :

<asp:DropDownList ID="Categories" runat="server" AppendDataBoundItems="True" 
    DataSourceID="CategoriesDataSource" DataTextField="CategoryName" 
    DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'>
    <asp:ListItem Value=">-- Select One --</asp:ListItem>
</asp:DropDownList>

Notez que l’attribut <asp:ListItem Value=""> -- Select One -- est Value explicitement défini sur une chaîne vide. Reportez-vous au didacticiel Personnalisation de l’interface de modification des données pour une discussion plus approfondie sur la raison pour laquelle cet élément DropDownList supplémentaire est nécessaire pour gérer le NULL cas et pourquoi l’affectation de la Value propriété à une chaîne vide est essentielle.

Notes

Il existe ici un problème potentiel de performances et d’extensibilité qui mérite d’être mentionné. Étant donné que chaque ligne a un DropDownList qui utilise comme CategoriesDataSource source de données, la méthode s de GetCategories la CategoriesBLL classe est appelée n fois par visite de page, où n est le nombre de lignes dans gridView. Ces n appels pour GetCategories générer n requêtes dans la base de données. Cet impact sur la base de données peut être atténué en mettant en cache les catégories retournées dans un cache par requête ou via la couche de mise en cache à l’aide d’une dépendance de mise en cache SQL ou d’une expiration basée sur le temps très court.

Étape 4 : Terminer l’interface d’édition

Nous avons apporté un certain nombre de modifications aux modèles GridView sans nous interrompre pour voir notre progression. Prenez un moment pour voir notre progression à l’aide d’un navigateur. Comme le montre la figure 13, chaque ligne est rendue à l’aide de son ItemTemplate, qui contient l’interface d’édition de cellule.

Chaque ligne GridView est modifiable

Figure 13 : Chaque ligne GridView est modifiable (cliquer pour afficher l’image en taille réelle)

Il y a quelques problèmes mineurs de mise en forme que nous devrions prendre en charge à ce stade. Tout d’abord, notez que la UnitPrice valeur contient quatre décimales. Pour résoudre ce problème, revenez aux UnitPrice TemplateField et ItemTemplate , à partir de la balise active textBox, cliquez sur le lien Modifier les liaisons de données. Ensuite, spécifiez que la Text propriété doit être mise en forme en tant que nombre.

Mettre en forme la propriété Text en tant que nombre

Figure 14 : Mettre en forme la Text propriété en tant que nombre

Ensuite, centons la case à cocher dans la Discontinued colonne (plutôt que de l’aligner à gauche). Cliquez sur Modifier les colonnes à partir de la balise active gridView et sélectionnez templateField Discontinued dans la liste des champs dans le coin inférieur gauche. ItemStyle Explorez et définissez la propriété sur Centre, comme illustré dans la HorizontalAlign figure 15.

Centrer le CheckBox discontinué

Figure 15 : Centrer la Discontinued case CheckBox

Ensuite, ajoutez un contrôle ValidationSummary à la page et définissez sa ShowMessageBox propriété sur true et sa ShowSummary propriété sur false. Ajoutez également les contrôles Button Web qui, lorsque vous cliquez dessus, mettent à jour les modifications de l’utilisateur. Plus précisément, ajoutez deux contrôles Web Button, l’un au-dessus de GridView et l’autre au-dessous, en définissant les deux propriétés des contrôles Text sur Mettre à jour les produits .

Étant donné que l’interface d’édition de GridView est définie dans ses TemplateFields ItemTemplate , les EditItemTemplate s sont superflus et peuvent être supprimés.

Après avoir apporté les modifications de mise en forme mentionnées ci-dessus, ajouté les contrôles Button et supprimé les s inutiles EditItemTemplate , la syntaxe déclarative de votre page doit se présenter comme suit :

<p>
    <asp:Button ID="UpdateAllProducts1" runat="server" Text="Update Products" />
</p>
<p>
    <asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
        AllowPaging="True" AllowSorting="True">
        <Columns>
            <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
                <ItemTemplate>
                    <asp:TextBox ID="ProductName" runat="server" 
                        Text='<%# Bind("ProductName") %>'></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                        ControlToValidate="ProductName"
                        ErrorMessage="You must provide the product's name." 
                        runat="server">*</asp:RequiredFieldValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Category" 
                SortExpression="CategoryName">
                <ItemTemplate>
                    <asp:DropDownList ID="Categories" runat="server" 
                        AppendDataBoundItems="True" 
                        DataSourceID="CategoriesDataSource"
                        DataTextField="CategoryName" 
                        DataValueField="CategoryID" 
                        SelectedValue='<%# Bind("CategoryID") %>'>
                        <asp:ListItem>-- Select One --</asp:ListItem>
                    </asp:DropDownList>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Price" 
                SortExpression="UnitPrice">
                <ItemTemplate>
                    $<asp:TextBox ID="UnitPrice" runat="server" Columns="8" 
                        Text='<%# Bind("UnitPrice", "{0:N}") %>'></asp:TextBox>
                    <asp:CompareValidator ID="CompareValidator1" runat="server" 
                        ControlToValidate="UnitPrice"
                        ErrorMessage="You must enter a valid currency value. 
                                      Please omit any currency symbols."
                        Operator="GreaterThanEqual" Type="Currency" 
                        ValueToCompare="0">*</asp:CompareValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
                <ItemTemplate>
                    <asp:CheckBox ID="Discontinued" runat="server" 
                        Checked='<%# Bind("Discontinued") %>' />
                </ItemTemplate>
                <ItemStyle HorizontalAlign="Center" />
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</p>
<p>
    <asp:Button ID="UpdateAllProducts2" runat="server" Text="Update Products" />
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetProducts" TypeName="ProductsBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetCategories" TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" 
        ShowMessageBox="True" ShowSummary="False" />
</p>

La figure 16 montre cette page lorsqu’elle est consultée via un navigateur après l’ajout des contrôles Web button et les modifications de mise en forme apportées.

La page inclut désormais deux boutons Mettre à jour les produits

Figure 16 : La page comprend désormais deux boutons Mettre à jour les produits (cliquer pour afficher l’image en taille réelle)

Étape 5 : Mise à jour des produits

Lorsqu’un utilisateur visite cette page, il apporte ses modifications, puis clique sur l’un des deux boutons Mettre à jour les produits. À ce stade, nous devons enregistrer les valeurs entrées par l’utilisateur pour chaque ligne dans un ProductsDataTable instance, puis passer cela à une méthode BLL qui transmettra ensuite cette ProductsDataTable instance à la méthode DALUpdateWithTransaction. La UpdateWithTransaction méthode, que nous avons créée dans le didacticiel précédent, garantit que le lot de modifications sera mis à jour en tant qu’opération atomique.

Créez une méthode nommée BatchUpdate dans BatchUpdate.aspx.cs et ajoutez le code suivant :

private void BatchUpdate()
{
    // Enumerate the GridView's Rows collection and create a ProductRow
    ProductsBLL productsAPI = new ProductsBLL();
    Northwind.ProductsDataTable products = productsAPI.GetProducts();
    foreach (GridViewRow gvRow in ProductsGrid.Rows)
    {
        // Find the ProductsRow instance in products that maps to gvRow
        int productID = Convert.ToInt32(ProductsGrid.DataKeys[gvRow.RowIndex].Value);
        Northwind.ProductsRow product = products.FindByProductID(productID);
        if (product != null)
        {
            // Programmatically access the form field elements in the 
            // current GridViewRow
            TextBox productName = (TextBox)gvRow.FindControl("ProductName");
            DropDownList categories = 
                (DropDownList)gvRow.FindControl("Categories");
            TextBox unitPrice = (TextBox)gvRow.FindControl("UnitPrice");
            CheckBox discontinued = 
                (CheckBox)gvRow.FindControl("Discontinued");
            // Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim();
            if (categories.SelectedIndex == 0) 
                product.SetCategoryIDNull(); 
            else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue);
            if (unitPrice.Text.Trim().Length == 0) 
                product.SetUnitPriceNull(); 
            else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text);
            product.Discontinued = discontinued.Checked;
        }
    }
    // Now have the BLL update the products data using a transaction
    productsAPI.UpdateWithTransaction(products);
}

Cette méthode commence par récupérer tous les produits dans un ProductsDataTable via un appel à la méthode BLL s GetProducts . Il énumère ensuite la ProductGrid collection gridViewRows. La Rows collection contient un GridViewRow instance pour chaque ligne affichée dans GridView. Étant donné que nous affichons au maximum dix lignes par page, la collection GridView n’aura Rows pas plus de dix éléments.

Pour chaque ligne, le ProductID est saisi à partir de la DataKeys collection et le approprié ProductsRow est sélectionné à partir de ProductsDataTable. Les quatre contrôles d’entrée TemplateField sont référencés par programmation et leurs valeurs sont affectées aux ProductsRow propriétés du instance. Une fois que les valeurs de chaque ligne GridView ont été utilisées pour mettre à jour , ProductsDataTableelles sont passées à la méthode BLL s UpdateWithTransaction qui, comme nous l’avons vu dans le tutoriel précédent, appelle simplement la méthode DAL.UpdateWithTransaction

L’algorithme de mise à jour par lots utilisé pour ce didacticiel met à jour chaque ligne du ProductsDataTable qui correspond à une ligne dans GridView, que les informations du produit ont ou non été modifiées. Bien que ces mises à jour aveugles ne soient généralement pas un problème de performances, elles peuvent entraîner des enregistrements superflus si vous auditez les modifications apportées à la table de base de données. De retour dans le didacticiel Exécution d’un lot Mises à jour nous avons exploré une interface de mise à jour par lots avec le DataList et ajouté du code qui ne mettait à jour que les enregistrements réellement modifiés par l’utilisateur. N’hésitez pas à utiliser les techniques de l’exécution de batch Mises à jour pour mettre à jour le code de ce tutoriel, si vous le souhaitez.

Notes

Lors de la liaison de la source de données à GridView via sa balise active, Visual Studio affecte automatiquement la ou les valeurs de clé primaire de la source de données à la propriété de DataKeyNames GridView. Si vous n’avez pas lié l’ObjectDataSource à GridView via la balise active GridView, comme indiqué à l’étape 1, vous devez définir manuellement la propriété de DataKeyNames GridView sur ProductID afin d’accéder à la ProductID valeur de chaque ligne dans la DataKeys collection.

Le code utilisé dans BatchUpdate est similaire à celui utilisé dans les méthodes BLL, UpdateProduct la main différence étant que dans les UpdateProduct méthodes, un seul ProductRow instance est récupéré à partir de l’architecture. Le code qui affecte les propriétés de est ProductRow le même entre les UpdateProducts méthodes et le code dans la foreach boucle dans BatchUpdate, tout comme le modèle global.

Pour suivre ce tutoriel, nous devons appeler la BatchUpdate méthode lorsque l’un des boutons Mettre à jour les produits est cliqué. Créez des gestionnaires d’événements pour les Click événements de ces deux contrôles Button et ajoutez le code suivant dans les gestionnaires d’événements :

BatchUpdate();
ClientScript.RegisterStartupScript(this.GetType(), "message", 
    "alert('The products have been updated.');", true);

Tout d’abord, un appel est effectué à BatchUpdate. Ensuite, le est utilisé pour injecter du ClientScript property code JavaScript qui affiche une boîte de message indiquant Les produits ont été mis à jour.

Prenez une minute pour tester ce code. Accédez BatchUpdate.aspx à un navigateur, modifiez un certain nombre de lignes, puis cliquez sur l’un des boutons Mettre à jour les produits. En supposant qu’il n’y ait pas d’erreurs de validation d’entrée, vous devriez voir une boîte de message indiquant Les produits ont été mis à jour. Pour vérifier l’atomicité de la mise à jour, envisagez d’ajouter une contrainte aléatoire CHECK , comme une contrainte qui interdit les UnitPrice valeurs de 1234,56. Ensuite, à partir de BatchUpdate.aspx, modifiez un certain nombre d’enregistrements, en veillant à définir l’une des valeurs du UnitPrice produit sur la valeur interdite ( 1234,56 ). Cela doit entraîner une erreur lorsque vous cliquez sur Mettre à jour les produits avec les autres modifications au cours de cette opération de traitement par lot restaurées à leurs valeurs d’origine.

Une autreBatchUpdateméthode

La BatchUpdate méthode que nous venons d’examiner récupère tous les produits de la méthode BLL, GetProducts puis met à jour uniquement les enregistrements qui apparaissent dans gridView. Cette approche est idéale si GridView n’utilise pas la pagination, mais si c’est le cas, il peut y avoir des centaines, des milliers ou des dizaines de milliers de produits, mais seulement dix lignes dans GridView. Dans ce cas, il n’est pas idéal d’obtenir tous les produits de la base de données pour en modifier 10.

Pour ces types de situations, envisagez plutôt d’utiliser la méthode suivante BatchUpdateAlternate :

private void BatchUpdateAlternate()
{
    // Enumerate the GridView's Rows collection and create a ProductRow
    ProductsBLL productsAPI = new ProductsBLL();
    Northwind.ProductsDataTable products = new Northwind.ProductsDataTable();
    foreach (GridViewRow gvRow in ProductsGrid.Rows)
    {
        // Create a new ProductRow instance
        int productID = Convert.ToInt32(ProductsGrid.DataKeys[gvRow.RowIndex].Value);
        
        Northwind.ProductsDataTable currentProductDataTable = 
            productsAPI.GetProductByProductID(productID);
        if (currentProductDataTable.Rows.Count > 0)
        {
            Northwind.ProductsRow product = currentProductDataTable[0];
            // Programmatically access the form field elements in the 
            // current GridViewRow
            TextBox productName = (TextBox)gvRow.FindControl("ProductName");
            DropDownList categories = 
                (DropDownList)gvRow.FindControl("Categories");
            TextBox unitPrice = (TextBox)gvRow.FindControl("UnitPrice");
            CheckBox discontinued = 
                (CheckBox)gvRow.FindControl("Discontinued");
            // Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim();
            if (categories.SelectedIndex == 0) 
                product.SetCategoryIDNull(); 
            else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue);
            if (unitPrice.Text.Trim().Length == 0) 
                product.SetUnitPriceNull(); 
            else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text);
            product.Discontinued = discontinued.Checked;
            // Import the ProductRow into the products DataTable
            products.ImportRow(product);
        }
    }
    // Now have the BLL update the products data using a transaction
    productsAPI.UpdateProductsWithTransaction(products);
}

BatchMethodAlternate commence par créer un nouveau vide ProductsDataTable nommé products. Il effectue ensuite le parcours de la collection GridView Rows et, pour chaque ligne, obtient les informations de produit particulières à l’aide de la méthode BLL.GetProductByProductID(productID) Le instance récupéré ProductsRow a ses propriétés mises à jour de la même manière que BatchUpdate, mais après la mise à jour de la ligne, il est importé dans le products``ProductsDataTable via la méthode DataTable sImportRow(DataRow).

Une fois la foreach boucle terminée, products contient une ProductsRow instance pour chaque ligne du GridView. Étant donné que ProductsRow chacune des instances a été ajoutée à ( products au lieu d’être mise à jour), si nous la passons aveuglément à la UpdateWithTransaction méthode, nous ProductsTableAdapter essayons d’insérer chacun des enregistrements dans la base de données. Au lieu de cela, nous devons spécifier que chacune de ces lignes a été modifiée (non ajoutée).

Pour ce faire, ajoutez une nouvelle méthode au BLL nommé UpdateProductsWithTransaction. UpdateProductsWithTransaction, illustré ci-dessous, définit le RowState de chacune des ProductsRow instances dans et ModifiedProductsDataTable passe ensuite à ProductsDataTable la méthode DAL sUpdateWithTransaction.

public int UpdateProductsWithTransaction(Northwind.ProductsDataTable products)
{
    // Mark each product as Modified
    products.AcceptChanges();
    foreach (Northwind.ProductsRow product in products)
        product.SetModified();
    // Update the data via a transaction
    return UpdateWithTransaction(products);
}

Résumé

GridView fournit des fonctionnalités d’édition par ligne intégrées, mais ne prend pas en charge la création d’interfaces entièrement modifiables. Comme nous l’avons vu dans ce tutoriel, de telles interfaces sont possibles, mais nécessitent un peu de travail. Pour créer un GridView où chaque ligne est modifiable, nous devons convertir les champs GridView en TemplateFields et définir l’interface de modification dans les ItemTemplate s. En outre, les contrôles Web Update All -type Button doivent être ajoutés à la page, séparément de GridView. Ces gestionnaires d’événements Buttons Click doivent énumérer la collection de GridView, Rows stocker les modifications dans un ProductsDataTableet transmettre les informations mises à jour dans la méthode BLL appropriée.

Dans le tutoriel suivant, nous allons voir comment créer une interface pour la suppression par lots. En particulier, chaque ligne GridView inclut une case à cocher et au lieu des boutons Mettre à jour tout -type, nous aurons des boutons Supprimer les lignes sélectionnées.

Bonne programmation !

À propos de l’auteur

Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille comme consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 in 24 Heures. Il est accessible à l’adressemitchell@4GuysFromRolla.com . ou via son blog, qui peut être trouvé à l’adresse http://ScottOnWriting.NET.

Un merci spécial à

Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Les réviseurs principaux de ce tutoriel étaient Teresa Murphy et David Suru. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.