演示文稿,业务和数据层

我刚刚开始使用C#进行编程,并且正在阅读将应用程序/网站划分为三个不同层次的文章,这是最佳实践,但我很难理解具体方法。 我正致力于一个宠物项目,更多地关注C#,但我不想从任何坏习惯开始。 你能看看我有什么,看看我做得对吗? 提供一些关于如何将所有内容分解为不同层次的提示建议?

表达层

    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">

业务层

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

数据访问层(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(string accessCode) { bool isValid = false; int count = 0; using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString)) { sqlCnn.Open(); using (SqlCommand sqlCmd = new SqlCommand(String.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.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString)) { sqlCnn.Open(); using (SqlCommand sqlCmd = new SqlCommand(String.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(string accessCode) { using (SqlConnection sqlCnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MusicLibraryConnectionString"].ConnectionString)) { sqlCnn.Open(); using (SqlCommand sqlCmd = new SqlCommand(String.Format("DELETE FROM [AccessCodes] WHERE [accessCode_accessCode] = '{0}';", accessCode), sqlCnn)) { sqlCmd.ExecuteNonQuery(); } } } } 

乔恩,

首先要理解的是,如果您打算构建基于层的应用程序,那么您不应该直接在ASPX页面中存储SQL语句(如SqlDataSource要求的那样)。 构建SqlDataSource控件是为了演示使用数据库数据绑定和更新应用程序是多么容易,并且不打算在现实世界的应用程序中使用,因为如果你打算使用BL层和Datalayer,它就会失败。存储在ASPX页面中选择/更新/删除/插入语句。

基于图层的应用程序设计的整个目的是封装每个层,以便没有交集。 每个层都与其他层的公共接口交互,并且对其内部实现一无所知。

因此,可行的替代方法是使用ObjectDataSource控件。 此控件允许您直接绑定到DataLayer或Biz逻辑层,而Biz逻辑层又可以调用Datalayer。 直接绑定到Datalayer的缺点是,您将返回公开数据库表模式的数据结构(例如,DataTables或DataViews)。

因此,推荐的逻辑流程如下:

ASPX页面使用DataSource控件绑定到BL类。 此BL类提供适当的函数,如GetData, UpdateData, DeleteData and InsertData (带有任何必需的重载),这些函数返回ObjectDataSource可以使用和显示的强类型对象或集合。 BL类中的每个公共函数在内部调用DataLayer来选择/更新/删除/插入数据库中的数据。

快速入门中提供了对ASP.NET中基于图层的设计的出色介绍

PS :@Andy提到了适用于所有场景的通用数据层。 请参阅此问题 ,了解它的外观示例。

ASP.NET应用程序中逻辑层的最佳解释来自两个来源。 第一个是由Scott Mitchell编写的微软自己的ASP.NET网站,它提供了对逻辑分离的良好介绍。 这些教程非常冗长,但我发现它们非常有用。 该URL是http://www.asp.net/learn/data-access/ 。

我发现第二个资源非常有用,它是由Imar Spaanjaars编写的,可以在这里找到 。 这是一篇技术性更强的文章,但提供了一种将结构添加到应用程序的好方法。

我希望有所帮助。

伊恩。

如果您编写的代码最终是可移植的,您会发现应用程序中有3个(或更多!)层。

例如 – 不要让您的数据访问层专门针对这个应用程序工作,而是编写它以便您永远不必再次编写它。 确保所有函数都可以传递变量,并且不依赖于全局变量(或尽可能少)。 当你的下一个项目到来时 – 复制并粘贴你的DAL,突然你又恢复了运行。

它并没有就此结束 – 您可能想为DAL编写一个子层,用于解释MySQL和MSSQL之间的区域(仅作为示例)。 或者您可能拥有一个常用function库,例如文本卫生或CSS生成等。

如果您编写代码以便有一天,您坐下来编写应用程序 – 它主要涉及剪切和粘贴以前的代码 – 您已经达到了程序员的必杀技。 🙂

分层应用程序背后的整个想法是每个层不依赖于下面的层的实现细节。 例如,在您的代码中,您在表示层中有一个T-SQL语句。 这意味着您的表示层与数据库(底层)直接相关。 如果在数据库中进行更改,则还必须在表示层中进行更改。 理想情况下,这不是你想要的。 表示层应仅关注呈现数据,而不关心如何检索数据。 假设您将整个数据库移动到CSV文件(我知道,疯狂的想法),那么您的表示层根本不应该意识到这一点。

理想情况下,您有一个业务层方法,只返回您要向用户显示的数据。 您应该看看ObjectDataSource而不是SqlDataSourceSqlDataSource适用于小型原型项目,但不应将其用于任何更严肃的项目。

在业务层和数据层之间,您应该有类似的分离。 数据层负责从某个存储位置(数据库,CSV文件,Web服务……)获取所需的数据。 同样,理想情况下,业务层不应该依赖于数据层的实现细节。 例如,如果您正在与SQL Server交谈,则不应将SqlDataReader实例返回到业务层。 通过这样做,您可以在数据层的实现细节上创建业务层的依​​赖关系:它从中检索数据的实际数据库。

在实践中,您会看到业务层确实以某种方式依赖于数据层的实现细节,通常这并不是一件坏事。 您最后一次决定何时切换数据库是什么时候? 但是,尽可能地消除依赖关系并隔离实现细节几乎总会导致应用程序更易于维护和理解。

你可以在这里找到类似的解释。

除了他的问题的主旨之外,我建议你看看ASPNET_REGSQL配置你的SQL数据库来处理.Net的内置成员资格/配置文件/角色能力。 它会消除很多用于创建/更新用户等的粗略和麻烦。我没有使用很多配置文件,但它允许你“为你的用户”添加额外的属性,例如AccessCode。

如果您正在处理已经进行用户身份validation等的现有数据库结构,则可以创建一个自定义成员资格提供程序,该提供程序将利用现有的数据库表和存储过程。