Contrôles de source de données
par Microsoft
Le contrôle DataGrid dans ASP.NET 1.x a marqué une grande amélioration de l’accès aux données dans les applications web. Toutefois, il n’était pas aussi convivial qu’il aurait pu l’être. Il fallait encore une quantité considérable de code pour obtenir des fonctionnalités très utiles à partir de celui-ci. Tel est le modèle dans toutes les tentatives d’accès aux données dans 1.x.
Le contrôle DataGrid dans ASP.NET 1.x a marqué une grande amélioration de l’accès aux données dans les applications web. Toutefois, il n’était pas aussi convivial qu’il aurait pu l’être. Il fallait encore une quantité considérable de code pour obtenir des fonctionnalités très utiles à partir de celui-ci. Tel est le modèle dans toutes les tentatives d’accès aux données dans 1.x.
ASP.NET 2.0 résout ce problème avec en partie avec des contrôles de source de données. Les contrôles de source de données dans ASP.NET 2.0 fournissent aux développeurs un modèle déclaratif pour récupérer des données, afficher des données et modifier des données. L’objectif des contrôles de source de données est de fournir une représentation cohérente des données aux contrôles liés aux données, quelle que soit la source de ces données. Au cœur des contrôles de source de données dans ASP.NET 2.0 se trouve la classe abstraite DataSourceControl. La classe DataSourceControl fournit une implémentation de base de l’interface IDataSource et de l’interface IListSource, cette dernière vous permettant d’affecter le contrôle de source de données en tant que DataSource d’un contrôle lié aux données (via la nouvelle propriété DataSourceId décrite plus loin) et d’exposer les données qui s’y trouvent sous forme de liste. Chaque liste de données d’un contrôle de source de données est exposée en tant qu’objet DataSourceView. L’accès aux instances DataSourceView est fourni par l’interface IDataSource. Par exemple, la méthode GetViewNames renvoie une ICollection qui vous permet d’énumérer les DataSourceViews associés à un contrôle de source de données particulier, et la méthode GetView vous permet d’accéder à un dataSourceView particulier instance par nom.
Les contrôles de source de données n’ont pas d’interface utilisateur. Ils sont implémentés en tant que contrôles serveur afin qu’ils puissent prendre en charge la syntaxe déclarative et qu’ils aient accès à l’état de la page si vous le souhaitez. Les contrôles de source de données ne restituent aucun balisage HTML au client.
Notes
Comme vous le verrez plus loin, il existe également des avantages de mise en cache obtenus à l’aide de contrôles de source de données.
Stockage des chaînes de connexion
Avant d’examiner comment configurer les contrôles de source de données, nous devons aborder une nouvelle fonctionnalité dans ASP.NET 2.0 concernant les chaînes de connexion. ASP.NET 2.0 introduit une nouvelle section dans le fichier de configuration qui vous permet de stocker facilement les chaînes de connexion qui peuvent être lues dynamiquement au moment de l’exécution. La <section connectionStrings> facilite le stockage des chaînes de connexion.
L’extrait de code ci-dessous ajoute une nouvelle chaîne de connexion.
<connectionStrings> <add name="Northwind" connectionString="Data Source=localhost; Integrated Security=SSPI;Initial Catalog=Northwind;" providerName="System.Data.SqlClient" /> </connectionStrings>
Notes
Tout comme pour la <section appSettings> , la <section connectionStrings> apparaît en dehors de la <section system.web> dans le fichier de configuration.
Pour utiliser cette chaîne de connexion, vous pouvez utiliser la syntaxe suivante lors de la définition de l’attribut ConnectionString d’un contrôle serveur.
ConnectionString="<%$ ConnectionStrings:Northwind%>"
La <section connectionStrings> peut également être chiffrée afin que les informations sensibles ne soient pas exposées. Cette capacité sera abordée dans un module ultérieur.
Mise en cache des sources de données
Chaque DataSourceControl fournit quatre propriétés pour la configuration de la mise en cache ; EnableCaching, CacheDuration, CacheExpirationPolicy et CacheKeyDependency.
EnableCaching
EnableCaching est une propriété booléenne qui détermine si la mise en cache est activée pour le contrôle de source de données.
CacheDuration, propriété
La propriété CacheDuration définit le nombre de secondes pendant lesquelles le cache reste valide. Si vous affectez la valeur 0 à cette propriété, le cache reste valide jusqu’à ce qu’il soit explicitement invalidé.
CacheExpirationPolicy, propriété
La propriété CacheExpirationPolicy peut être définie sur Absolute ou Sliding. La définition de la valeur Absolute signifie que la durée maximale pendant laquelle les données seront mises en cache est le nombre de secondes spécifié par la propriété CacheDuration. En la définissant sur Glissant, le délai d’expiration est réinitialisé lorsque chaque opération est effectuée.
CacheKeyDependency, propriété
Si une valeur de chaîne est spécifiée pour la propriété CacheKeyDependency, ASP.NET configurez une nouvelle dépendance de cache basée sur cette chaîne. Cela vous permet d’invalider explicitement le cache en modifiant ou en supprimant simplement cacheKeyDependency.
Important : si l’emprunt d’identité est activé et que l’accès à la source de données et/ou au contenu des données est basé sur l’identité du client, il est recommandé de désactiver la mise en cache en définissant EnableCaching sur False. Si la mise en cache est activée dans ce scénario et qu’un utilisateur autre que l’utilisateur qui a initialement demandé les données émet une demande, l’autorisation à la source de données n’est pas appliquée. Les données seront simplement servies à partir du cache.
Contrôle SqlDataSource
Le contrôle SqlDataSource permet à un développeur d’accéder aux données stockées dans n’importe quelle base de données relationnelle prenant en charge ADO.NET. Il peut utiliser le fournisseur System.Data.SqlClient pour accéder à une base de données SQL Server, le fournisseur System.Data.OleDb, le fournisseur System.Data.Odbc ou le fournisseur System.Data.OracleClient pour accéder à Oracle. Par conséquent, SqlDataSource n’est certainement pas utilisé uniquement pour accéder aux données d’une base de données SQL Server.
Pour utiliser SqlDataSource, il vous suffit de fournir une valeur pour la propriété ConnectionString et de spécifier une commande SQL ou une procédure stockée. Le contrôle SqlDataSource s’occupe de l’utilisation de l’architecture ADO.NET sous-jacente. Il ouvre la connexion, interroge la source de données ou exécute la procédure stockée, retourne les données, puis ferme la connexion pour vous.
Notes
Étant donné que la classe DataSourceControl ferme automatiquement la connexion pour vous, elle doit réduire le nombre d’appels clients générés par la fuite de connexions aux bases de données.
L’extrait de code ci-dessous lie un contrôle DropDownList à un contrôle SqlDataSource à l’aide de la chaîne de connexion stockée dans le fichier de configuration, comme indiqué ci-dessus.
<asp:SqlDataSource id="SqlDataSource1" runat="server" DataSourceMode="DataReader" ConnectionString="<%$ ConnectionStrings:Northwind%>" SelectCommand="SELECT EmployeeID, LastName FROM Employees"> </asp:SqlDataSource><asp:DropDownList id="ListBox1" runat="server" DataTextField="LastName" DataValueField="EmployeeID" DataSourceID="SqlDataSource1"> </asp:DropDownList>
Comme illustré ci-dessus, la propriété DataSourceMode de SqlDataSource spécifie le mode de la source de données. Dans l’exemple ci-dessus, dataSourceMode est défini sur DataReader. Dans ce cas, SqlDataSource retourne un objet IDataReader à l’aide d’un curseur en lecture seule et en lecture seule. Le type spécifié d’objet retourné est contrôlé par le fournisseur utilisé. Dans ce cas, j’utilise le fournisseur System.Data.SqlClient comme spécifié dans la <section connectionStrings> du fichier web.config. Par conséquent, l’objet retourné sera de type SqlDataReader. En spécifiant une valeur DataSourceMode de DataSet, les données peuvent être stockées dans un DataSet sur le serveur. Ce mode vous permet d’ajouter des fonctionnalités telles que le tri, la pagination, etc. Si j’avais lier des données sqlDataSource à un contrôle GridView, j’aurais choisi le mode DataSet. Toutefois, dans le cas d’un DropDownList, le mode DataReader est le bon choix.
Notes
Lors de la mise en cache d’un SqlDataSource ou d’un AccessDataSource, la propriété DataSourceMode doit être définie sur DataSet. Une exception se produit si vous activez la mise en cache avec un DataSourceMode de DataReader.
Propriétés de SqlDataSource
Voici quelques-unes des propriétés du contrôle SqlDataSource.
CancelSelectOnNullParameter
Valeur booléenne qui spécifie si une commande select est annulée si l’un des paramètres a la valeur Null. La valeur par défaut est True.
ConflictDetection
Dans une situation où plusieurs utilisateurs peuvent mettre à jour une source de données en même temps, la propriété ConflictDetection détermine le comportement du contrôle SqlDataSource. Cette propriété correspond à l’une des valeurs de l’énumération ConflictOptions. Ces valeurs sont CompareAllValues et OverwriteChanges. Si la valeur est OverwriteChanges, la dernière personne à écrire des données dans la source de données remplace les modifications précédentes. Toutefois, si la propriété ConflictDetection est définie sur CompareAllValues, les paramètres sont créés pour les colonnes retournées par la SelectCommand et les paramètres sont également créés pour contenir les valeurs d’origine dans chacune de ces colonnes, ce qui permet à SqlDataSource de déterminer si les valeurs ont changé depuis l’exécution de SelectCommand.
Deletecommand
Définit ou obtient la chaîne SQL utilisée lors de la suppression de lignes de la base de données. Il peut s’agir d’une requête SQL ou d’un nom de procédure stockée.
DeleteCommandType
Définit ou obtient le type de commande delete, soit une requête SQL (Texte) soit une procédure stockée (StoredProcedure).
DeleteParameters
Retourne les paramètres utilisés par deleteCommand de l’objet SqlDataSourceView associé au contrôle SqlDataSource.
OldValuesParameterFormatString
Cette propriété est utilisée pour spécifier le format des paramètres de valeur d’origine dans les cas où la propriété ConflictDetection est définie sur CompareAllValues. La valeur par défaut est {0} ce qui signifie que les paramètres de valeur d’origine prendront le même nom que le paramètre d’origine. En d’autres termes, si le nom du champ est EmployeeID, le paramètre de valeur d’origine est @EmployeeID.
SelectCommand
Définit ou obtient la chaîne SQL utilisée pour récupérer des données de la base de données. Il peut s’agir d’une requête SQL ou d’un nom de procédure stockée.
SelectCommandType
Définit ou obtient le type de commande select, soit une requête SQL (Texte) soit une procédure stockée (StoredProcedure).
SélectionnerParamètres
Retourne les paramètres utilisés par l’objet SelectCommand de l’objet SqlDataSourceView associé au contrôle SqlDataSource.
SortParameterName
Obtient ou définit le nom d’un paramètre de procédure stockée utilisé lors du tri des données récupérées par le contrôle de source de données. Valide uniquement lorsque SelectCommandType est défini sur StoredProcedure.
SqlCacheDependency
Chaîne délimitée par des points-virgules spécifiant les bases de données et les tables utilisées dans une dépendance de cache SQL Server. (Les dépendances du cache SQL seront abordées dans un module ultérieur.)
Updatecommand
Définit ou obtient la chaîne SQL utilisée lors de la mise à jour des données dans la base de données. Il peut s’agir d’une requête SQL ou d’un nom de procédure stockée.
UpdateCommandType
Définit ou obtient le type de commande de mise à jour, soit une requête SQL (Texte) soit une procédure stockée (StoredProcedure).
UpdateParameters
Retourne les paramètres utilisés par updateCommand de l’objet SqlDataSourceView associé au contrôle SqlDataSource.
Contrôle AccessDataSource
Le contrôle AccessDataSource dérive de la classe SqlDataSource et est utilisé pour lier des données à une base de données Microsoft Access. La propriété ConnectionString du contrôle AccessDataSource est une propriété en lecture seule. Au lieu d’utiliser la propriété ConnectionString, la propriété DataFile est utilisée pour pointer vers la base de données Access, comme indiqué ci-dessous.
<asp:AccessDataSource id="AccessDataSource1" runat="server" DataFile="~/App_Data/Northwind.mdb"> </asp:AccessDataSource>
AccessDataSource définit toujours le ProviderName du SqlDataSource de base sur System.Data.OleDb et se connecte à la base de données à l’aide du fournisseur OLE DB Microsoft.Jet.OLEDB.4.0. Vous ne pouvez pas utiliser le contrôle AccessDataSource pour vous connecter à une base de données Access protégée par mot de passe. Si vous devez vous connecter à une base de données protégée par mot de passe, vous devez utiliser le contrôle SqlDataSource.
Notes
Les bases de données Access stockées dans le site Web doivent être placées dans le répertoire App_Data. ASP.NET n’autorise pas la navigation dans les fichiers de ce répertoire. Vous devez accorder au compte de processus des autorisations de lecture et d’écriture sur le répertoire App_Data lors de l’utilisation de bases de données Access.
Contrôle XmlDataSource
XmlDataSource est utilisé pour lier des données XML à des contrôles liés aux données. Vous pouvez lier à un fichier XML à l’aide de la propriété DataFile ou vous pouvez lier à une chaîne XML à l’aide de la propriété Data. XmlDataSource expose les attributs XML en tant que champs pouvant être liés. Dans les cas où vous devez lier des valeurs qui ne sont pas représentées en tant qu’attributs, vous devez utiliser une transformation XSL. Vous pouvez également utiliser des expressions XPath pour filtrer les données XML.
Considérez le fichier XML suivant :
<?xml version="1.0" encoding="utf-8" ?> <People> <Person FirstName="Jake" LastName="Stone"> <Address> <Street>345 Maple St.</Street> <City>Redmond</City> <Region>WA</Region> <ZipCode>01434</ZipCode> </Address> <Job> <Title>CEO</Title> <Description>Develops company strategies.</Description> </Job> </Person> <Person FirstName="Jacob" LastName="Ladder"> <Address> <Street>123 Elm St.</Street> <City>Seattle</City> <Region>WA</Region> <ZipCode>11223</ZipCode> </Address> <Job> <Title>Attorney</Title> <Description>Reviews legal issues.</Description> </Job> </Person> <Person FirstName="Angela" LastName="Hound"> <Address> <Street>34 Palm Avenue</Street> <City>Renton</City> <Region>WA</Region> <ZipCode>63910</ZipCode> </Address> <Job> <Title>IT Director</Title> <Description>In charge of corporate network.</Description> </Job> </Person> </People>
Notez que XmlDataSource utilise une propriété XPath de Personnes/Person pour filtrer uniquement sur les <nœuds Person>. Le DropDownList lie ensuite les données à l’attribut LastName à l’aide de la propriété DataTextField.
Bien que le contrôle XmlDataSource soit principalement utilisé pour lier des données à des données XML en lecture seule, il est possible de modifier le fichier de données XML. Notez que dans ce cas, l’insertion, la mise à jour et la suppression automatiques des informations dans le fichier XML ne se produisent pas automatiquement comme avec d’autres contrôles de source de données. Au lieu de cela, vous devrez écrire du code pour modifier manuellement les données à l’aide des méthodes suivantes du contrôle XmlDataSource.
GetXmlDocument
Récupère un objet XmlDocument contenant le code XML récupéré par xmlDataSource.
Enregistrer
Enregistre le XmlDocument en mémoire dans la source de données.
Il est important de réaliser que la méthode Save ne fonctionne que lorsque les deux conditions suivantes sont remplies :
- XmlDataSource utilise la propriété DataFile pour établir une liaison à un fichier XML au lieu de la propriété Data à lier à des données XML en mémoire.
- Aucune transformation n’est spécifiée via la propriété Transform ou TransformFile.
Notez également que la méthode Save peut produire des résultats inattendus lorsqu’elle est appelée simultanément par plusieurs utilisateurs.
Contrôle ObjectDataSource
Les contrôles de source de données que nous avons couverts jusqu’ici sont d’excellents choix pour les applications à deux niveaux où le contrôle de source de données communique directement avec le magasin de données. Toutefois, de nombreuses applications réelles sont des applications multiniveau où un contrôle de source de données peut avoir besoin de communiquer avec un objet métier qui, à son tour, communique avec la couche de données. Dans ces situations, ObjectDataSource remplit la facture correctement. ObjectDataSource fonctionne conjointement avec un objet source. Le contrôle ObjectDataSource crée une instance de l’objet source, appelle la méthode spécifiée et élimine l’objet instance tous dans l’étendue d’une requête unique, si votre objet a instance méthodes au lieu de méthodes statiques (Partagé en Visual Basic). Par conséquent, votre objet doit être sans état. Autrement dit, votre objet doit acquérir et libérer toutes les ressources requises dans l’intervalle d’une requête unique. Vous pouvez contrôler la façon dont l’objet source est créé en gérant l’événement ObjectCreating du contrôle ObjectDataSource. Vous pouvez créer une instance de l’objet source, puis définir la propriété ObjectInstance de la classe ObjectDataSourceEventArgs sur cette instance. Le contrôle ObjectDataSource utilise le instance créé dans l’événement ObjectCreating au lieu de créer un instance seul.
Si l’objet source d’un contrôle ObjectDataSource expose des méthodes statiques publiques (partagée en Visual Basic) qui peuvent être appelées pour récupérer et modifier des données, un contrôle ObjectDataSource appelle ces méthodes directement. Si un contrôle ObjectDataSource doit créer un instance de l’objet source pour effectuer des appels de méthode, l’objet doit inclure un constructeur public qui ne prend aucun paramètre. Le contrôle ObjectDataSource appelle ce constructeur lorsqu’il crée une nouvelle instance de l’objet source.
Si l’objet source ne contient pas de constructeur public sans paramètres, vous pouvez créer un instance de l’objet source qui sera utilisé par le contrôle ObjectDataSource dans l’événement ObjectCreating.
Spécification de méthodes d’objet
L’objet source d’un contrôle ObjectDataSource peut contenir un nombre quelconque de méthodes utilisées pour sélectionner, insérer, mettre à jour ou supprimer des données. Ces méthodes sont appelées par le contrôle ObjectDataSource en fonction du nom de la méthode, comme identifié à l’aide de la propriété SelectMethod, InsertMethod, UpdateMethod ou DeleteMethod du contrôle ObjectDataSource. L’objet source peut également inclure une méthode SelectCount facultative, identifiée par le contrôle ObjectDataSource à l’aide de la propriété SelectCountMethod, qui retourne le nombre total d’objets à la source de données. Le contrôle ObjectDataSource appelle la méthode SelectCount après l’appel d’une méthode Select pour récupérer le nombre total d’enregistrements au niveau de la source de données à utiliser lors de la pagination.
Labo utilisant des contrôles de source de données
Exercice 1 : Affichage des données avec le contrôle SqlDataSource
L’exercice suivant utilise le contrôle SqlDataSource pour se connecter à la base de données Northwind. Elle suppose que vous avez accès à la base de données Northwind sur une SQL Server 2000 instance.
Créez un site web ASP.NET.
Ajoutez un nouveau fichier web.config.
- Cliquez avec le bouton droit sur le projet dans Explorateur de solutions, puis cliquez sur Ajouter un nouvel élément.
- Choisissez Fichier de configuration web dans la liste des modèles, puis cliquez sur Ajouter.
Modifiez la <section connectionStrings> comme suit :
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ConnectionStrings:Northwind%>" SelectCommand="SELECT * FROM Products"> </asp:SqlDataSource>
Basculez vers la vue Code et ajoutez un attribut ConnectionString et un attribut SelectCommand au <contrôle asp:SqlDataSource> comme suit :
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ConnectionStrings:Northwind%>" SelectCommand="SELECT * FROM Products"> </asp:SqlDataSource>
En mode Création, ajoutez un nouveau contrôle GridView.
Dans la liste déroulante Choisir une source de données dans le menu Tâches GridView, choisissez SqlDataSource1.
Cliquez avec le bouton droit sur Default.aspx et choisissez Afficher dans le navigateur dans le menu. Cliquez sur Oui lorsque vous êtes invité à enregistrer.
GridView affiche les données de la table Products.
Exercice 2 - Modification de données avec le contrôle SqlDataSource
L’exercice suivant montre comment lier des données à un contrôle DropDownList à l’aide de la syntaxe déclarative et vous permet de modifier les données présentées dans le contrôle DropDownList.
En mode Création, supprimez le contrôle GridView de Default.aspx.
Important : laissez le contrôle SqlDataSource sur la page.
Ajoutez un contrôle DropDownList à Default.aspx.
Basculez vers la vue Source.
Ajoutez un attribut DataSourceId, DataTextField et DataValueField au <contrôle asp:DropDownList> comme suit :
<asp:DropDownList ID="ddlProducts" runat="server" DataSourceId="SqlDataSource1" DataTextField="ProductName" DataValueField="ProductID"> </asp:DropDownList>
Enregistrez Default.aspx et affichez-le dans le navigateur. Notez que la liste DropDownList contient tous les produits de la base de données Northwind.
Fermez le navigateur.
Dans la vue Source de Default.aspx, ajoutez un nouveau contrôle TextBox sous le contrôle DropDownList. Remplacez la propriété ID de TextBox par txtProductName.
Sous le contrôle TextBox, ajoutez un nouveau contrôle Button. Remplacez la propriété ID du bouton par btnUpdate et la propriété Text par Mettre à jour le nom du produit.
Dans la vue Source de Default.aspx, ajoutez une propriété UpdateCommand et deux nouveaux UpdateParameters à la balise SqlDataSource comme suit :
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ConnectionStrings:Northwind%>" SelectCommand="SELECT * FROM Products" UpdateCommand="UPDATE Products SET ProductName=@ProductName WHERE ProductID=@ProductID"> <UpdateParameters> <asp:ControlParameter Name="ProductName" ControlID="txtProductName" PropertyName="Text" /> <asp:ControlParameter Name="ProductID" ControlID="ddlProducts" PropertyName="SelectedValue" /> </asp:SqlDataSource>
Notes
Notez que deux paramètres de mise à jour (ProductName et ProductID) sont ajoutés dans ce code. Ces paramètres sont mappés à la propriété Text de txtProductName TextBox et à la propriété SelectedValue de ddlProducts DropDownList.
Basculez en mode Création et double-cliquez sur le contrôle Button pour ajouter un gestionnaire d’événements.
Ajoutez le code suivant au code btnUpdate_Click :
SqlDataSource1.Update();
Cliquez avec le bouton droit sur Default.aspx et choisissez de l’afficher dans le navigateur. Cliquez sur Oui lorsque vous êtes invité à enregistrer toutes les modifications.
ASP.NET classes partielles 2.0 autorisent la compilation au moment de l’exécution. Il n’est pas nécessaire de créer une application pour que les modifications de code prennent effet.
Sélectionnez un produit dans la liste déroulante.
Entrez un nouveau nom pour le produit sélectionné dans textBox, puis cliquez sur le bouton Mettre à jour.
Le nom du produit est mis à jour dans la base de données.
Exercice 3 Utilisation du contrôle ObjectDataSource
Cet exercice montre comment utiliser le contrôle ObjectDataSource et un objet source pour interagir avec la base de données Northwind.
Cliquez avec le bouton droit sur le projet dans Explorateur de solutions, puis cliquez sur Ajouter un nouvel élément.
Sélectionnez Formulaire web dans la liste des modèles. Remplacez le nom par object.aspx, puis cliquez sur Ajouter.
Cliquez avec le bouton droit sur le projet dans Explorateur de solutions, puis cliquez sur Ajouter un nouvel élément.
Sélectionnez Classe dans la liste des modèles. Remplacez le nom de la classe par NorthwindData.cs, puis cliquez sur Ajouter.
Cliquez sur Oui lorsque vous êtes invité à ajouter la classe au dossier App_Code.
Ajoutez le code suivant au fichier NorthwindData.cs :
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Data.SqlClient; public class NorthwindData { private string _connectionString; public NorthwindData() { Initialize(); } private void Initialize() { if (ConfigurationManager.ConnectionStrings["Northwind"] == null || ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == "") { throw new Exception("A connection string named 'Northwind' with " + "a valid connection string must exist in the <connectionStrings> " + "configuration section for the application."); } _connectionString = ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString; } public DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords) { VerifySortColumns(sortColumns); string sqlCmd = "SELECT EmployeeID, LastName, FirstName, Address, " + "City, Region, PostalCode FROM Employees "; if (sortColumns.Trim() == "") sqlCmd += "ORDER BY EmployeeID"; else sqlCmd += "ORDER BY " + sortColumns; SqlConnection conn = new SqlConnection(_connectionString); SqlDataAdapter da = new SqlDataAdapter(sqlCmd, conn); DataSet ds = new DataSet(); try { conn.Open(); da.Fill(ds, startRecord, maxRecords, "Employees"); } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return ds.Tables["Employees"]; } public int SelectCount() { SqlConnection conn = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Employees", conn); int result = 0; try { conn.Open(); result = (int)cmd.ExecuteScalar(); } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return result; } ////////// // Verify that only valid columns are specified in the sort expression to // avoid a SQL Injection attack. private void VerifySortColumns(string sortColumns) { if (sortColumns.ToLowerInvariant().EndsWith(" desc")) sortColumns = sortColumns.Substring(0, sortColumns.Length - 5); string[] columnNames = sortColumns.Split(','); foreach (string columnName in columnNames) { switch (columnName.Trim().ToLowerInvariant()) { case "employeeid": break; case "lastname": break; case "firstname": break; case "": break; default: throw new ArgumentException("SortColumns contains an " + "invalid column name."); break; } } } // Select an employee. public DataTable GetEmployee(int EmployeeID) { SqlConnection conn = new SqlConnection(_connectionString); SqlDataAdapter da = new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, " + "Address, City, Region, PostalCode " + " FROM Employees WHERE EmployeeID = @EmployeeID", conn); da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID; DataSet ds = new DataSet(); try { conn.Open(); da.Fill(ds, "Employees"); } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return ds.Tables["Employees"]; } // Delete the Employee by ID. public int DeleteEmployee(int EmployeeID) { SqlConnection conn = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand("DELETE FROM Employees WHERE " + "EmployeeID = @EmployeeID", conn); cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID; int result = 0; try { conn.Open(); result = cmd.ExecuteNonQuery(); } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return result; } // Update the Employee by original ID. public int UpdateEmployee(int EmployeeID, string LastName, string FirstName, string Address, string City, string Region, string PostalCode) { if (String.IsNullOrEmpty(FirstName)) throw new ArgumentException("FirstName cannot be null or an empty string."); if (String.IsNullOrEmpty(LastName)) throw new ArgumentException("LastName cannot be null or an empty string."); if (Address == null) { Address = String.Empty; } if (City == null) { City = String.Empty; } if (Region == null) { Region = String.Empty; } if (PostalCode == null) { PostalCode = String.Empty; } SqlConnection conn = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand("UPDATE Employees " + " SET FirstName=@FirstName, " + "LastName=@LastName, " + "Address=@Address, City=@City, " + "Region=@Region, " + "PostalCode=@PostalCode " + "WHERE EmployeeID=@EmployeeID", conn); cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName; cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName; cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address; cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City; cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region; cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode; cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID; int result = 0; try { conn.Open(); result = cmd.ExecuteNonQuery(); } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return result; } // Insert an Employee. public int InsertEmployee(string LastName, string FirstName, string Address, string City, string Region, string PostalCode) { if (String.IsNullOrEmpty(FirstName)) throw new ArgumentException("FirstName cannot be null or an empty string."); if (String.IsNullOrEmpty(LastName)) throw new ArgumentException("LastName cannot be null or an empty string."); if (Address == null) { Address = String.Empty; } if (City == null) { City = String.Empty; } if (Region == null) { Region = String.Empty; } if (PostalCode == null) { PostalCode = String.Empty; } SqlConnection conn = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand("INSERT INTO Employees " + " (FirstName, LastName, Address, " + " City, Region, PostalCode) " + " Values(@FirstName, @LastName, " + "@Address, @City, @Region, @PostalCode); " + "SELECT @EmployeeID = SCOPE_IDENTITY()", conn); cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName; cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName; cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address; cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City; cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region; cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode; SqlParameter p = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int); p.Direction = ParameterDirection.Output; int newEmployeeID = 0; try { conn.Open(); cmd.ExecuteNonQuery(); newEmployeeID = (int)p.Value; } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return newEmployeeID; } // // Methods that support Optimistic Concurrency checks. // // Delete the Employee by ID. public int DeleteEmployee(int original_EmployeeID, string original_LastName, string original_FirstName, string original_Address, string original_City, string original_Region, string original_PostalCode) { if (String.IsNullOrEmpty(original_FirstName)) throw new ArgumentException("FirstName cannot be null or an empty string."); if (String.IsNullOrEmpty(original_LastName)) throw new ArgumentException("LastName cannot be null or an empty string."); if (original_Address == null) { original_Address = String.Empty; } if (original_City == null) { original_City = String.Empty; } if (original_Region == null) { original_Region = String.Empty; } if (original_PostalCode == null) { original_PostalCode = String.Empty; } string sqlCmd = "DELETE FROM Employees WHERE EmployeeID = " + @original_EmployeeID SqlConnection conn = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(sqlCmd, conn); cmd.Parameters.Add("@original_EmployeeID", SqlDbType.Int).Value = original_EmployeeID; cmd.Parameters.Add("@original_FirstName", SqlDbType.VarChar, 10).Value = original_FirstName; cmd.Parameters.Add("@original_LastName", SqlDbType.VarChar, 20).Value = original_LastName; cmd.Parameters.Add("@original_Address", SqlDbType.VarChar, 60).Value = original_Address; cmd.Parameters.Add("@original_City", SqlDbType.VarChar, 15).Value = original_City; cmd.Parameters.Add("@original_Region", SqlDbType.VarChar, 15).Value = original_Region; cmd.Parameters.Add("@original_PostalCode", SqlDbType.VarChar, 10).Value = original_PostalCode; int result = 0; try { conn.Open(); result = cmd.ExecuteNonQuery(); } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return result; } // Update the Employee by original ID. public int UpdateEmployee(string LastName, string FirstName, string Address, string City, string Region, string PostalCode, int original_EmployeeID, string original_LastName, string original_FirstName, string original_Address, string original_City, string original_Region, string original_PostalCode) { if (String.IsNullOrEmpty(FirstName)) throw new ArgumentException("FirstName cannot be null or an empty string."); if (String.IsNullOrEmpty(LastName)) throw new ArgumentException("LastName cannot be null or an empty string."); if (Address == null) { Address = String.Empty; } if (City == null) { City = String.Empty; } if (Region == null) { Region = String.Empty; } if (PostalCode == null) { PostalCode = String.Empty; } if (original_Address == null) { original_Address = String.Empty; } if (original_City == null) { original_City = String.Empty; } if (original_Region == null) { original_Region = String.Empty; } if (original_PostalCode == null) { original_PostalCode = String.Empty; } string sqlCmd = "UPDATE Employees " + " SET FirstName = @FirstName, LastName = @LastName, " + " Address = @Address, City = @City, Region = @Region, " + " PostalCode = @PostalCode " + " WHERE EmployeeID = @original_EmployeeID"; SqlConnection conn = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(sqlCmd, conn); cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName; cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName; cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address; cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City; cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region; cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode; cmd.Parameters.Add("@original_EmployeeID", SqlDbType.Int).Value = original_EmployeeID; cmd.Parameters.Add("@original_FirstName", SqlDbType.VarChar, 10).Value = original_FirstName; cmd.Parameters.Add("@original_LastName", SqlDbType.VarChar, 20).Value = original_LastName; cmd.Parameters.Add("@original_Address", SqlDbType.VarChar, 60).Value = original_Address; cmd.Parameters.Add("@original_City", SqlDbType.VarChar, 15).Value = original_City; cmd.Parameters.Add("@original_Region", SqlDbType.VarChar, 15).Value = original_Region; cmd.Parameters.Add("@original_PostalCode", SqlDbType.VarChar, 10).Value = original_PostalCode; int result = 0; try { conn.Open(); result = cmd.ExecuteNonQuery(); } catch (SqlException e) { // Handle exception. } finally { conn.Close(); } return result; } }
Ajoutez le code suivant à la vue Source de object.aspx :
<%@ Page language="C#" %> <script RunAt="server"> void EmployeesDetailsView_ItemInserted(Object sender, DetailsViewInsertedEventArgs e) { EmployeesGridView.DataBind(); } void EmployeesDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e) { EmployeesGridView.DataBind(); } void EmployeesDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e) { EmployeesGridView.DataBind(); } void EmployeesGridView_OnSelectedIndexChanged(object sender, EventArgs e) { EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue = EmployeesGridView.SelectedDataKey.Value.ToString(); EmployeesDetailsView.DataBind(); } void EmployeeDetailsObjectDataSource_OnInserted(object sender, ObjectDataSourceStatusEventArgs e) { EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue = e.ReturnValue.ToString(); EmployeesDetailsView.DataBind(); } void EmployeeDetailsObjectDataSource_OnUpdated(object sender, ObjectDataSourceStatusEventArgs e) { if ((int)e.ReturnValue == 0) Msg.Text = "Employee was not updated. Please try again."; } void EmployeeDetailsObjectDataSource_OnDeleted(object sender, ObjectDataSourceStatusEventArgs e) { if ((int)e.ReturnValue == 0) Msg.Text = "Employee was not deleted. Please try again."; } void Page_Load() { Msg.Text = ""; } </script> <html> <body> <form id="Form1" runat="server"> <h3>ObjectDataSource Example</h3> <asp:Label id="Msg" runat="server" ForeColor="Red" /> <asp:ObjectDataSource ID="EmployeesObjectDataSource" runat="server" TypeName="NorthwindData" SortParameterName="SortColumns" EnablePaging="true" SelectCountMethod="SelectCount" StartRowIndexParameterName="StartRecord" MaximumRowsParameterName="MaxRecords" SelectMethod="GetAllEmployees" > </asp:ObjectDataSource> <asp:ObjectDataSource ID="EmployeeDetailsObjectDataSource" runat="server" TypeName="NorthwindData" ConflictDetection="CompareAllValues" OldValuesParameterFormatString="{0}" SelectMethod="GetEmployee" InsertMethod="InsertEmployee" UpdateMethod="UpdateEmployee" DeleteMethod="DeleteEmployee" OnInserted="EmployeeDetailsObjectDataSource_OnInserted" OnUpdated="EmployeeDetailsObjectDataSource_OnUpdated" OnDeleted="EmployeeDetailsObjectDataSource_OnDeleted"> <SelectParameters> <asp:Parameter Name="EmployeeID" Type="Int32" /> </SelectParameters> </asp:ObjectDataSource> <table cellspacing="10"> <tr> <td valign="top"> <asp:GridView ID="EmployeesGridView" DataSourceID="EmployeesObjectDataSource" AutoGenerateColumns="false" AllowSorting="true" AllowPaging="true" PageSize="5" DataKeyNames="EmployeeID" OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged" RunAt="server"> <HeaderStyle backcolor="lightblue" forecolor="black"/> <Columns> <asp:ButtonField Text="Details..." HeaderText="Show Details" CommandName="Select"/> <asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" SortExpression="EmployeeID" /> <asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" /> <asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpression="LastName, FirstName" /> </Columns> </asp:GridView> </td> <td valign="top"> <asp:DetailsView ID="EmployeesDetailsView" DataSourceID="EmployeeDetailsObjectDataSource" AutoGenerateRows="false" EmptyDataText="No records." DataKeyNames="EmployeeID" Gridlines="Both" AutoGenerateInsertButton="true" AutoGenerateEditButton="true" AutoGenerateDeleteButton="true" OnItemInserted="EmployeesDetailsView_ItemInserted" OnItemUpdated="EmployeesDetailsView_ItemUpdated" OnItemDeleted="EmployeesDetailsView_ItemDeleted" RunAt="server"> <HeaderStyle backcolor="Navy" forecolor="White"/> <RowStyle backcolor="White"/> <AlternatingRowStyle backcolor="LightGray"/> <EditRowStyle backcolor="LightCyan"/> <Fields> <asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisible="False" ReadOnly="true"/> <asp:BoundField DataField="FirstName" HeaderText="First Name"/> <asp:BoundField DataField="LastName" HeaderText="Last Name"/> <asp:BoundField DataField="Address" HeaderText="Address"/> <asp:BoundField DataField="City" HeaderText="City"/> <asp:BoundField DataField="Region" HeaderText="Region"/> <asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/> </Fields> </asp:DetailsView> </td> </tr> </table> </form> </body> </html>
Enregistrez tous les fichiers et parcourez object.aspx.
Interagissez avec l’interface en affichant les détails, en modifiant des employés, en ajoutant des employés et en supprimant des employés.