Présentation, couche métier et couche de données

Je venais juste de commencer à programmer en C # et je lisais à propos de la division de votre application / site Web en trois couches différentes. C’était la meilleure pratique, mais j’ai du mal à comprendre exactement comment. Je travaille sur un projet animalier pour en apprendre davantage sur C # mais je ne veux pas commencer avec de mauvaises habitudes. Pouvez-vous regarder ce que j’ai et voir si je le fais bien? Proposez quelques astuces sur la manière de tout décomposer en différentes couches?

Couche de présentation

    Project: Ruth    
" class="lnk">Link <asp:SqlDataSource ID="sdsLibrary" runat="server" ConnectionString="" DeleteCommand="DELETE FROM [Library] WHERE [lib_id] = @lib_id" InsertCommand="INSERT INTO [Library] ([artist_name], [album_title], [song_title], [file_path]) VALUES (@artist_name, @album_title, @song_title, @file_path)" ProviderName="" SelectCommand="SELECT [lib_id], [artist_name], [album_title], [song_title], [file_path] FROM [Library] ORDER BY [artist_name], [album_title]" UpdateCommand="UPDATE [Library] SET [artist_name] = @artist_name, [album_title] = @album_title, [song_title] = @song_title, [file_path] = @file_path WHERE [lib_id] = @lib_id">

Couche métier

 using System; using System.Collections.Generic; using System.Linq; using System.Web; public class User { DA da = new DA(); public ssortingng FirstName { get; set; } public ssortingng LastName { get; set; } public ssortingng EmailAddress { get; set; } public ssortingng Password { get; set; } public ssortingng AccessCode { get; set; } public User(ssortingng firstName, ssortingng lastName, ssortingng emailAddress, ssortingng password, ssortingng accessCode) { FirstName = firstName; LastName = lastName; EmailAddress = emailAddress; Password = password; AccessCode = accessCode; } public void CreateUser(User newUser) { if (da.IsValidAccessCode(newUser.AccessCode)) { da.CreateUser(newUser); } } } 

Couche d’access aux données (DAL)

 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data; using System.Data.SqlTypes; using System.Data.SqlClient; using System.Configuration; public class DA { public DA() { } public bool IsValidAccessCode(ssortingng accessCode) { bool isValid = false; int count = 0; using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionSsortingngs["MusicLibraryConnectionSsortingng"].ConnectionSsortingng)) { sqlCnn.Open(); using (SqlCommand sqlCmd = new SqlCommand(Ssortingng.Format("SELECT COUNT(*) FROM [AccessCodes] WHERE [accessCode_accessCode] = '{0}';", accessCode), sqlCnn)) { count = (int)sqlCmd.ExecuteScalar(); if (count == 1) { isValid = true; } } } return isValid; } public void CreateUser(User newUser) { using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionSsortingngs["MusicLibraryConnectionSsortingng"].ConnectionSsortingng)) { sqlCnn.Open(); using (SqlCommand sqlCmd = new SqlCommand(Ssortingng.Format("INSERT INTO [Users] (user_firstName, user_lastName, user_emailAddress, user_password, user_accessCode) VALUES ('{0}', '{1}', '{2}', '{3}', '{4}');", newUser.FirstName, newUser.LastName, newUser.EmailAddress, newUser.Password, newUser.AccessCode), sqlCnn)) { sqlCmd.ExecuteNonQuery(); } } DeleteAccessCode(newUser.AccessCode); } public void DeleteAccessCode(ssortingng accessCode) { using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionSsortingngs["MusicLibraryConnectionSsortingng"].ConnectionSsortingng)) { sqlCnn.Open(); using (SqlCommand sqlCmd = new SqlCommand(Ssortingng.Format("DELETE FROM [AccessCodes] WHERE [accessCode_accessCode] = '{0}';", accessCode), sqlCnn)) { sqlCmd.ExecuteNonQuery(); } } } } 

Jon,

Une des premières choses à comprendre est que si vous avez l’intention de créer des applications basées sur des couches, vous ne devriez pas stocker les instructions SQL directement dans des pages ASPX (comme le requirejs SqlDataSource ). Le contrôle SqlDataSource été créé pour montrer à quel point il est facile de lier et de mettre à jour une application avec des données de firebase database. Il n’est pas destiné à être utilisé dans des applications du monde réel, car il va un peu à l’encontre de l’objective de disposer d’une couche BL et de Datalayer si vous allez store Sélectionnez les instructions / Update / Delete / Insert dans la page ASPX.

Le but de la conception d’applications basées sur des couches est d’encapsuler chaque couche de manière à ce qu’il n’y ait pas d’intersection. Chaque couche interagit avec l’interface publique des autres couches et ignore tout de leur implémentation interne.

L’alternative viable consiste donc à utiliser le contrôle ObjectDataSource . Ce contrôle vous permet de vous lier directement à un DataLayer ou à une couche logique Biz qui peut à son tour appeler le Datalayer. La liaison directe à un calque de données a l’inconvénient de renvoyer des structures de données qui exposent le schéma des tables de la firebase database (par exemple, DataTables ou DataViews).

Ainsi, le stream de logique recommandé est le suivant:

La page ASPX utilise un contrôle DataSource pour se lier à une classe BL. Cette classe BL fournit des fonctions appropriées telles que GetData, UpdateData, DeleteData and InsertData (avec les surcharges requirejses). Ces fonctions renvoient des objects fortement typés ou des collections que ObjectDataSource peut ObjectDataSource et afficher. Chaque fonction publique de la classe BL appelle en interne dans le DataLayer pour sélectionner / mettre à jour / supprimer / insérer des données dans / à partir de la firebase database.

Une introduction excellente à cette conception basée sur la couche dans ASP.NET est fournie dans les Quickstarts

PS : @Andy a mentionné des générateurs de données génériques qui fonctionnent avec tous les scénarios. Voir cette question pour un exemple de ce à quoi cela pourrait ressembler.

La plus grande explication des couches logiques dans les applications ASP.NET provient de deux sources. Le premier est le site Web ASP.NET de Microsoft, écrit par Scott Mitchell. Il fournit une bonne introduction à la séparation de la logique. Les tutoriels sont assez verbeux mais je les ai trouvés très utiles. L’URL est http://www.asp.net/learn/data-access/ .

La deuxième ressource que j’ai trouvée très utile, qui a été écrite par Imar Spaanjaars, est disponible ici . C’est un article beaucoup plus technique mais qui fournit un excellent moyen d’append la structure à votre application.

J’espère que ça aide.

Ian.

Si vous écrivez votre code pour être finalement portable, vous constaterez que vous aurez 3 couches (ou plus!) Dans votre application.

Par exemple, au lieu de faire en sorte que votre couche d’access aux données fonctionne spécifiquement pour cette application, écrivez-la afin que vous n’ayez plus jamais à l’écrire. Assurez-vous que toutes vos fonctions peuvent être transmises à des variables et que vous ne comptez pas sur des variables globales (ou le moins possible). Le moment venu pour votre prochain projet – copiez et collez votre DAL et tout à coup, vous êtes à nouveau opérationnel.

Et cela ne s’arrête pas là. Vous voudrez peut-être écrire une sous-couche pour votre DAL qui interprète entre MySQL et MSSQL (juste à titre d’exemple). Vous pouvez également avoir une bibliothèque de fonctions courantes que vous effectuez, telles que la purification de texte ou la génération de CSS, etc.

Si vous écrivez votre code de manière à ce qu’un jour, vous vous assoyiez pour écrire une application (ce qui implique principalement de couper et coller du code précédent), vous avez atteint le programmeur nirvana. 🙂

La superposition d’une application à une couche repose essentiellement sur l’idée que chaque couche ne dépend pas des détails d’implémentation de la ou des couches ci-dessous. Par exemple, dans votre code, vous avez une instruction T-SQL dans votre couche de présentation. Cela signifie que votre couche de présentation dépend directement de votre firebase database (la couche inférieure). Si vous modifiez votre firebase database, vous devez également modifier votre couche de présentation. Idéalement, ce n’est pas ce que vous voulez. La couche de présentation ne doit s’intéresser qu’à la présentation des données, pas à la manière de les récupérer. Supposons que vous déplaciez toute votre firebase database dans des fichiers CSV (je sais, idée folle), votre couche de présentation ne devrait en être absolument pas consciente.

Donc, idéalement, vous avez une méthode de couche de gestion qui renvoie uniquement les données que vous souhaitez afficher à l’utilisateur. Vous devriez jeter un coup d’oeil à ObjectDataSource au lieu de SqlDataSource . SqlDataSource convient aux petits projets de prototypage, mais vous ne devez pas l’utiliser pour des projets plus sérieux.

Entre la couche de gestion et la couche de données, vous devriez avoir une séparation similaire. La couche de données est chargée de récupérer les données souhaitées depuis un emplacement de stockage (firebase database, fichier CSV, service Web, …). Encore une fois, idéalement, la couche de gestion ne devrait pas dépendre des détails de mise en œuvre de la couche de données. Si vous parlez à SQL Server, par exemple, vous ne devez pas renvoyer d’instance SqlDataReader à votre couche de SqlDataReader . En faisant cela, vous créez une dépendance de votre couche métier sur un détail d’implémentation de votre couche de données: la firebase database à partir de laquelle elle récupère ses données.

En pratique, vous constatez que la couche de gestion dépend des détails d’implémentation de la couche de données d’une manière ou d’une autre, ce qui n’est généralement pas une mauvaise chose. Quand était la dernière fois que vous avez décidé de changer de firebase database? Toutefois, éliminer les dépendances et isoler autant que possible les détails de la mise en œuvre permet presque toujours de rendre l’application plus facile à gérer et à comprendre.

Vous pouvez trouver une explication similaire ici .

En plus de l’essentiel de sa question, je vous recommanderais de consulter ASPNET_REGSQL pour configurer votre firebase database SQL afin de gérer les capacités intégrées d’appartenance, de profil et de rôle .Net. Cela enlèverait beaucoup de difficultés pour créer / mettre à jour des utilisateurs, etc. Je n’ai pas utilisé beaucoup de profil, mais cela vous permet de “rappend” des atsortingbuts supplémentaires à votre utilisateur, par exemple AccessCode.

Si vous traitez avec une structure de firebase database existante qui effectue déjà l’authentification d’utilisateur, etc., vous pouvez créer un fournisseur d’adhésion personnalisé qui exploiterait les tables de firebase database existantes et les procédures stockées.