Mise à jour par lots (C#)
par Scott Mitchell
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.
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 ItemTemplate
place 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 ID
ProductsGrid
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
.
Figure 2 : Configurer ObjectDataSource pour utiliser la ProductsBLL
classe (cliquer pour afficher l’image en taille réelle)
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.
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 ProductName
champs sauf les champs , CategoryName
, UnitPrice
et 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
, CategoryName
et 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.
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 desProductName
UnitPrice
Discontinued
interfaces
La création des ProductName
interfaces , UnitPrice
et 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 ID
ProductName
.
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 à , ItemTemplate
votre écran doit ressembler à la figure 6.
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é Currency
sur , sa Operator
propriété sur GreaterThanEqual
et sa ValueToCompare
propriété sur 0 .
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
, ItemTemplate
en 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 , ItemTemplate
ce 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
.
Figure 8 : Configurer ObjectDataSource pour utiliser la CategoriesBLL
classe (cliquer pour afficher l’image en taille réelle)
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.
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.
Figure 11 : Lier la liste déroulante à (CategoriesDataSource
Cliquer 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.
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.
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.
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.
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.
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 , ProductsDataTable
elles 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 autreBatchUpdate
mé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 Modified
ProductsDataTable
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 ProductsDataTable
et 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.