如何在 ASP.NET 中组织数据访问层 (DAL)
Posted
技术标签:
【中文标题】如何在 ASP.NET 中组织数据访问层 (DAL)【英文标题】:How to organize Data Access Layer (DAL) in ASP.NET 【发布时间】:2012-01-05 13:38:32 【问题描述】:我有一个用 C# 开发的 ASP.NET Web 窗体应用程序。
我想通过将 DAL 任务与背后的代码分开来构建我的应用程序。
我在 App_Code 中创建了一个类 DBUtilities,它负责与数据库的通信,以避免整个应用程序中出现重复的代码。该类具有获取数据表、标量值等的方法……它们接受 连接字符串名称 和 查询命令 作为参数作为字符串。
问题是我的代码中仍然有所有查询的命令。其中许多在页面周围重复,这会导致维护问题。
我想知道创建一个包含许多 字符串属性 的(静态)类 QueryRepository 并为每个属性关联一个特定的查询命令是否是一个好习惯。每次我想执行查询命令 MyCommand 时,我都会将字符串的 QueryRepository.MyCommand
属性传递给 DBUtilities 类。此外,如果我需要更改查询命令,我只在 QueryRepository 类上进行。
这是组织我的 DAL 的好方法吗?
【问题讨论】:
【参考方案1】:对于 ASP.NET Web 表单,实现 Model-View-Presenter (MVP) 模式可能是将您的逻辑和数据库查询与背后的 UI 代码分离的一种好方法。您必须编写一个 Presenter 类,该类具有对视图接口的通用引用,并且其中有一个模型,其中包含数据库查询、逻辑等。演示器将在其所有函数中调用通用视图接口的函数。然后您可以编写实际的 ASP.net 视图。在视图中,您实例化并引用此演示者,并在实例化演示者时将 self 对象,即 ASP 视图本身(使用“this”关键字)注入演示者。您可以根据需要为您的演示者类设计适当的继承,以便它们可重用并且可以进行单元测试。
针对 CiccioMiami 的询问添加:
这里有几个链接开始
http://www.codeproject.com/KB/aspnet/AspNet_MVP.aspx
http://wiki.asp.net/page.aspx/340/mvp-pattern/
这里解释了 MVC 和 MVP 模式的区别:http://www.codeproject.com/KB/architecture/DotNetMVPFramework_Part1.aspx
此外,对于 ASP.net Web 表单架构,请求与页面生命周期紧密耦合。您有一系列页面生命周期事件,开发人员在每个事件中编写代码。因此,业务逻辑与 UI 视图紧密耦合。在一段时间内,这对于代码可维护性和单元测试来说不是一个好情况。 ASP.net Web 表单中的单元测试很困难,因为它很难模拟请求和页面生命周期事件。在 MVC 中,请求首先到达控制器。控制器将模型用于业务逻辑并将模型传递给视图。视图使用模型数据呈现,并作为响应返回给用户。控制器对工作流程有更大的控制。您可以像在独立应用程序中一样测试模型、DTO 传输等。对于 Web 表单,没有控制器,请求直接到达作为视图的 ASP.net 页面。用户无能为力。很好,微软意识到了这个问题,我们有 ASP.net MVC。 ASP.net webforms 的 MVP 模式将在一定程度上解决代码分离问题。最好的选择是使用 ASP.net MVC,如果没有,那么您可以将 MVP 与 Webforms 一起使用。
【讨论】:
哇,这看起来是个不错的解决方案。你知道任何关于在 ASP.NET 中实现 MVP 的教程吗?它与 MVC 有何不同(模式不是框架)【参考方案2】:长期回答:我真的可以推荐你阅读Professional Enterprise .NET
ASP.NET 网站上有一个很好的 repository pattern 示例,值得一看。
我不是专家,但如果您的 DAL 能够符合最佳实践模式,那么它更有可能成为组织它的好方法。
我很难在没有具体示例的情况下遵循您的 DAL 设计,因此不确定我是否可以提供帮助。
【讨论】:
谢谢,但您的链接是指 MVC 框架。我使用 ASP.NET Web 窗体 我认为该链接很好地描述了未链接到 mvc 的存储库模式。 +1【参考方案3】:几个步骤:
将 DAL、BLL 代码与表示 (UI) 层分离是一种很好的做法,但相应地执行以下步骤会有所帮助。
-
创建 DTO(数据传输对象)或实体
从表示层填充 DTO/实体
将其传递给 BLL 层的公共方法并验证业务逻辑
然后将 DTO/Entity 传递给 DAL 层(在 DAL 层,创建一个返回 Command 的方法,然后将您的 CommandText、CommandType 和设置值、数据类型和大小设置为所有参数,同时创建执行方法得到命令并返回结果)。
最后,执行你想要的执行方法(在 DAL 层创建)
【讨论】:
【参考方案4】:namespace DAL
public class DBAccess
private IDbCommand cmd = new SqlCommand();
private string strConnectionString = "";
private bool handleErrors = false;
private string strLastError = "";
public DBAccess()
ConnectionStringSettings objConnectionStringSettings = ConfigurationManager.ConnectionStrings["connectionString"];
strConnectionString = objConnectionStringSettings.ConnectionString;
SqlConnection cnn = new SqlConnection();
cnn.ConnectionString = strConnectionString;
cmd.Connection = cnn;
cmd.CommandType = CommandType.StoredProcedure;
public SqlConnection OpenSqlConnection()
try
SqlConnection Conn = new SqlConnection(strConnectionString);
Conn.Open();
return Conn;
catch (SqlException e)
throw e;
catch (Exception ex)
throw ex;
public IDataReader ExecuteReader()
IDataReader reader = null;
try
this.Open();
reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
catch (Exception ex)
if (handleErrors)
strLastError = ex.Message;
else
throw;
return reader;
public IDataReader ExecuteReader(string commandtext)
IDataReader reader = null;
try
cmd.CommandText = commandtext;
reader = this.ExecuteReader();
catch (Exception ex)
if ((handleErrors))
strLastError = ex.Message;
else
throw;
return reader;
public object ExecuteScalar()
object obj = null;
try
this.Open();
obj = cmd.ExecuteScalar();
this.Close();
catch (Exception ex)
if (handleErrors)
strLastError = ex.Message;
else
throw;
return obj;
public object ExecuteScalar(string commandtext)
object obj = null;
try
cmd.CommandText = commandtext;
obj = this.ExecuteScalar();
catch (Exception ex)
if ((handleErrors))
strLastError = ex.Message;
else
throw;
return obj;
public int ExecuteNonQuery(SqlConnection DBConnection, SqlTransaction DBTransaction, bool IsTransRequired)
int i = -1;
try
if ((DBTransaction != null))
cmd.Transaction = DBTransaction;
i = cmd.ExecuteNonQuery();
catch (Exception ex)
if (handleErrors)
strLastError = ex.Message;
else
throw;
return i;
public int ExecuteNonQuery(string commandtext, bool IsTransRequired)
SqlConnection DBConnection = null;
SqlTransaction DBTransaction = null;
int i = -1;
try
cmd.CommandText = commandtext;
if (((DBConnection == null)))
this.Open();
DBConnection = (SqlConnection)this.cmd.Connection;
if (IsTransRequired == true)
if (((DBTransaction == null)))
DBTransaction = DBConnection.BeginTransaction();
i = this.ExecuteNonQuery(DBConnection, DBTransaction, IsTransRequired);
if ((DBTransaction != null))
DBTransaction.Commit();
catch (Exception ex)
if ((DBTransaction != null))
DBTransaction.Rollback();
if (handleErrors)
strLastError = ex.Message;
else
throw;
finally
this.Close();
return i;
public DataSet ExecuteDataSet()
SqlDataAdapter da = null;
DataSet ds = null;
try
da = new SqlDataAdapter();
da.SelectCommand = (SqlCommand)cmd;
ds = new DataSet();
da.Fill(ds);
catch (Exception ex)
if ((handleErrors))
strLastError = ex.Message;
else
throw;
return ds;
public DataSet ExecuteDataSet(string commandtext)
DataSet ds = null;
try
cmd.CommandText = commandtext;
ds = this.ExecuteDataSet();
catch (Exception ex)
if (handleErrors)
strLastError = ex.Message;
else
throw;
return ds;
public string CommandText
get
return cmd.CommandText;
set
cmd.CommandText = value;
cmd.Parameters.Clear();
public IDataParameterCollection Parameters
get return cmd.Parameters;
public void AddParameter(string paramname, object paramvalue)
SqlParameter param = new SqlParameter(paramname, paramvalue);
cmd.Parameters.Add(param);
public void AddParameter(IDataParameter param)
cmd.Parameters.Add(param);
public string ConnectionString
get return strConnectionString;
set strConnectionString = value;
private void Open()
cmd.Connection.Open();
private void Close()
cmd.Connection.Close();
public bool HandleExceptions
get return handleErrors;
set handleErrors = value;
public string LastError
get return strLastError;
public void Dispose()
cmd.Dispose();
【讨论】:
以上是关于如何在 ASP.NET 中组织数据访问层 (DAL)的主要内容,如果未能解决你的问题,请参考以下文章
在ASP.NET中,三层架构,Web ,BLL,DAL,Models这四个的引用关系是?