使用缓存机制的通用加载下拉列表数据






4.42/5 (7投票s)
本文向您展示如何利用 DataAccessLayer 和缓存。
引言
当我尝试学习如何从数据库加载数据到 DropDownList
时,作为新手,我最初不得不花费大量时间搜索。一旦我将 DropDownList
加载了数据,就出现了许多实现问题,例如是使用 DataReader
还是 DataSet
。完成之后,又出现了性能问题,以及如何在 DropDown 中为用户提供额外的文本,例如“Select Item”。为了完成以上所有工作,我不得不花费大量时间浏览各种 .NET 网站。因此,我决定撰写这篇文章,提供开发任何应用程序所需的全部功能。我使用了现有的数据库“NorthWind”。所以您无需自己创建数据库。
DataAccessLayer
我将从 DataAccessLayer
开始,可以在其中创建一个 DataAccess
类(DataAccessLayer.cs)。此类包含用于连接字符串、SQL 查询语句等的构造函数,具体取决于任何应用程序的需求。在此类中,我还定义了 ConnectionString
和 SelectStmOnCat
属性。客户端可以设置和获取这些属性。基本上,在我们的情况下,客户端是表示层,可以在其中声明属性值并访问它们。下面的代码仅为您提供上述功能的亮点。但我未将其包含在我的代码中。
DataAccessLayer.DataAccess objDac=new DataAccess();
objDac.ConnectionString=strConn;
objDac.SelectStmOnCat=strSelectCat;
为了展示如何使用参数化构造函数,我在表示层,即 DropDown.aspx.cs 中使用了下面的声明。
DataAccessLayer.DataAccess objDac=new DataAccess(strConn,strSelectCat);
public class DataAccess
{
//Private member
private string strConn;
private string strSelectCat;
public DataAccess()
{
//
// TODO: Add constructor logic here
//Initialization
strConn=null;
strSelectCat=null;
}
public DataAccess(string _strConn,string _strSelectCat)
{
//parameterized constructor;
strConn=_strConn;
strSelectCat=_strSelectCat;
}
//set connectionstring property
//this has been done just to show how property can be defined
public string ConnectionString
{
get
{
return strConn;
}
set
{
strConn=value;
}
}
}
现在让我们看一下下面的方法
public DataTable LoadCategoryInDropDownList()
//PreCondition: Take Connection Object, SQL Query.
//PostCondition: Return DataTable containing Category list.
//Process: Fill Datatable with category from NorthWind _db
此方法有三个逻辑块。因此,我们从 t
ry
语句开始。在此,我打开了与数据库 SQL Server 的连接。您会注意到,我试图使此过程更加通用和可重用。我使用了“Using
语句”。此“Using
”语句确保一旦创建了 DataAdapter
对象,它将在所需过程完成后关闭。它不会等待垃圾回收器来完成。我使用此方法是为了提高内存性能。
using(SqlDataAdapter objAdpOnCat=new SqlDataAdapter(strSelectCat,objConn))
try
{
objConn.Open();
//Using helps to dispose object as soon as
//required process gets complete
using(SqlDataAdapter objAdpOnCat=new SqlDataAdapter (strSelectCat,objConn))
{
objAdpOnCat.Fill(tblCategory);
}
}
我跳过了 catch
块,因为它不言自明。
catch(SqlException e)
{
throw new Exception("Invalid Connection Error Occured "+e.Message);
}
继续向下阅读该块,我们可以看到
finally
{
if(objConn.State.ToString()=="Open")
{
objConn.Dispose();
objConn.Close();
}
}
在 finally 块中,我为了内存管理关闭了连接对象。这样做是最佳实践。我希望到目前为止您都理解了。
完整的 DataAccessLayer.cs 代码
namespace DataAccessLayer
{
/// <SUMMARY>
/// Summary description for DataAccessLayer.
/// This is a generic code for loading data from any database..
/// One can also use OleDb for more generalized coding....
/// </SUMMARY>
public class DataAccess
{
//Private member
private string strConn;
private string strSelectCat;
public DataAccess()
{
// TODO: Add constructor logic here
//Initialization
strConn=null;
strSelectCat=null;
}
public DataAccess(string _strConn,string _strSelectCat)
{
//parameterized constructor;
strConn=_strConn;//Connection String
strSelectCat=_strSelectCat;//Sql query statement
}
//set connectionstring property
//this has been done just to show how property can be defined
public string ConnectionString
{
get { return strConn; }
set { strConn=value; }
}
public string SelectStmOnCat
{
get { return strSelectCat; }
set { strSelectCat=value; }
}
//PreCondition:Take Connection Object, Sql Query
//PostCondition:Return DataTable containing Category list
//Process:Fill Datatable with category from Northwind _db
public DataTable LoadCategoryInDropDownList()
{
SqlConnection objConn=new SqlConnection(strConn);
DataTable tblCategory =new DataTable();
try
{
objConn.Open();
//Using helps to dispose object as soon as
//required process gets complete
using(SqlDataAdapter objAdpOnCat=new SqlDataAdapter(strSelectCat,objConn))
{
objAdpOnCat.Fill(tblCategory);
}
}
catch(SqlException e)
{
throw new Exception("Invalid Connection Error Occured "+e.Message);
}
finally
{
if(objConn.State.ToString()=="Open")
{
objConn.Dispose();
objConn.Close();
}
}
return tblCategory;
}
}
}
配置设置
我在 Web.confiq 文件中声明并定义了连接字符串,以便可以在应用程序中全局使用相同的连接字符串。您也可以加密此连接字符串并解密它。我们现在不讨论这些。
在编写代码的过程中,你学到了什么有趣/好玩/令人恼火的东西吗? 你做了什么特别巧妙、疯狂或异想天开的事情吗?
<appSettings>
<!-- User application and configured property settings go here.-->
<!-- Example: <add key="settingName" value="settingValue"/gt -->
<add key="DSNConn" value="SERVER=ITL232;DATABASE=Northwind;UID=sa;PWD=sa" />
</appSettings>
可以使用以下代码行提取连接字符串
protected static string strConn=
System.Configuration.ConfigurationSettings.AppSettings["DSNConn"];
缓存:性能提升
现在让我们看一下在 DropDown.aspx.cs 文件中声明的代码。
using System.Web.Caching;
为了使用缓存机制,请在代码中包含 System.Web.Caching
。缓存是一个非常有用的机制,可以用来提高应用程序的性能。我已声明
DataTable tblCategories = (DataTable) Cache["Categories"];
最初,我将缓存的表名“Categories
”分配给 tblCategories
。现在,我们来关注非常有趣的概念。我们经常离开当前 aspx 页面并跳转到下一个 aspx 页面。有时,我们可能会再次访问同一页面,并看到页面前端块中的相同数据。例如,我有一个 DropDownList
,其中加载了数据库中的数据。现在我离开此页面并跳转到下一页。用户可能再次回到具有该下拉列表的页面。在这种情况下,我们不会从数据库加载数据,而是从缓存内存加载。因此,我们避免了调用重要资源以及打开与数据库的新连接的往返。从而,我们在应用程序中获得了性能的提升和更高的吞吐量。
查看代码,我们发现如果缓存表为空(null
),我们将从“NorthWind”数据库将 DataTable
加载到缓存中,有效期为一小时。每次页面加载时,都会检查缓存内存中的 DataTable
,如果缓存内存中有数据,则从中获取。
Cache.Insert("Categories", tblCategories, null, DateTime.Now.AddHours(1),
Cache.NoSlidingExpiration);
在这里,您可以指定以绝对时间间隔或自上次访问以来的时间间隔为单位的到期日期。绝对到期时间为 1 小时:DateTime.Now.AddHours(1)
public void Insert ( System.String key , System.Object value ,
System.Web.Caching.CacheDependency dependencies ,
System.DateTime absoluteExpiration ,
System.TimeSpan slidingExpiration ,
System.Web.Caching.CacheItemPriority priority ,
System.Web.Caching.CacheItemRemovedCallback onRemoveCallback )
Member of System.Web.Caching.Cache
提示:将对象插入 System.Web.Caching.Cache
对象,并指定依赖项、过期和优先级策略,以及一个委托,您可以使用该委托在插入的项目从缓存中移除时通知您的应用程序。
有关上述输入参数,请参考 MSDN。
这里是加载 DropDownList
数据的 FetchCategory
方法。
public void FetchCategory()
{
//----------------
DataAccessLayer.DataAccess objDac=new DataAccess(strConn,strSelectCat);
DataTable tblCategories = (DataTable) Cache["Categories"];
if (tblCategories == null)
{
tblCategories = new DataTable();
tblCategories=objDac.LoadCategoryInDropDownList();
// It inserts new row in filled datatable.
//This new row contains static data for user
//instruction Text such as" Select the Item"
DataRow dr=tblCategories.NewRow();
dr["CategoryID"]=0;
dr["CategoryName"]="--Select Item--";
tblCategories.Rows.InsertAt(dr,0);
//Cache The DataTable in a Cache Memory for duration of one hour...
Cache.Insert("Categories", tblCategories, null,
DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
}
//---------------------
}
在 DropDownList 中添加静态说明文本
现在让我们看看如何在使用数据库加载 Dropdown 后添加静态说明文本。我创建了一个新的行到 DataTable
中,并将其插入到索引零的位置。希望到目前为止这一切都很容易理解。
DataRow dr=tblCategories.NewRow();
dr["CategoryID"]=0;
dr["CategoryName"]="--Select Item--";
tblCategories.Rows.InsertAt(dr,0);
结论
我的主要目标是让学习者更熟悉面向对象的编程方式。当多个用户连接到应用程序时,考虑性能以减少瓶颈非常重要。这是我的第一篇文章,希望我已满足了学习者的一些期望。欢迎任何建议和批评。