65.9K
CodeProject 正在变化。 阅读更多。
Home

静态数据助手 (ASP.NET 2.0)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (5投票s)

2006 年 10 月 21 日

CPOL

4分钟阅读

viewsIcon

88800

downloadIcon

677

一个用于管理下拉列表静态数据并支持缓存的辅助类。

引言

这是一个简单的辅助类,旨在管理 ASP.NET 应用程序中的静态数据。该辅助类将从 SQL Server 数据库检索多个静态数据表,将数据存储在 DataSet 中,并在应用程序启动时或首次请求时进行缓存。只需一行代码即可从缓存中获取数据并将其绑定到 ListControlDropDownList / ListBox / RadioButtonList / CheckBoxList)。

背景

如果您曾经开发过包含大量 DropDownList 控件的 Web 应用程序,那么您可能会发现自己会重复编写大量代码。需要编写代码从数据库中获取查找数据,缓存数据,并将其绑定到 DropDownList 控件,可能是在多个页面上。

设置数据库

演示应用程序使用 SQL Server 2005 Express Edition 开发,但相同的概念也适用于 SQL Server 2000。演示中有一个简单的数据库,包含三个表,用于存储类别、状态和类型的查找值。有一个存储过程:proc_StaticDataSelect,用于通过多个结果集检索这三个表的数据。

CREATE PROCEDURE dbo.proc_StaticDataSelect
AS
	SET NOCOUNT ON;
	
SELECT StatusId, Status FROM [Statuses]	
	
SELECT TypeId, Type FROM [Types]	
	
SELECT CategoryId, Category, Description FROM [Categories]

使用代码

在示例应用程序的 App_Code 文件夹中有一个类,名为 StaticData.cs。在该类的顶部附近,有一个名为 Tables 的枚举,其中包含每个结果集的值,并且顺序与存储过程返回的顺序相同。

    public enum Tables
    {
        Statuses = 0,
        Types,
        Categories
    }

公共方法 Bind 从缓存中检索静态数据并将其绑定到 ListControlDropDownList / ListBox / RadioButtonList / CheckBoxList)。它接受 ListControl 和表索引作为参数,还有一个重载版本允许向 ListControl 添加标题行。

将静态数据绑定到名为 TypeFilterDropDownList

    <asp:DropDownList ID="TypeFilter" runat="server"></asp:DropDownList>
    StaticData.Bind(this.TypeFilter, StaticData.Tables.Types, "All Types");

Tables 枚举用于指示 DataSet 中表的索引。这可以避免使用数字来表示离散值。

公共方法 CacheStaticData 从数据库获取静态数据并将其缓存到 DataSet 中。此方法可以在 Global.asaxApplication_Start 事件中调用。如果不在应用程序启动时调用;它将在第一次调用 Bind 方法时被调用。

    void Application_Start(object sender, EventArgs e) 
    {        
        StaticData.CacheStaticData();
    }

要为另一个 ListControl 添加数据,只需将一个 SELECT 语句添加到 proc_StaticDataSelect 存储过程中,并在 Tables 枚举中添加相同索引的表名。然后,您就可以将数据绑定到 ListControl,数据将与其余静态数据一起检索和缓存。

工作原理

在演示中,所有代码都在 StaticData 类中,尽管数据访问代码可以放在单独的类或项目中。

GetDataSet 方法建立数据库连接,并通过 SqlDataReader 获取数据。它使用 DataSetLoad 方法将多个结果集加载到一个 DataSet 中。*(根据您的配置,您可能需要在 web.config 中修改连接字符串。)*

    private static DataSet GetDataSet()
    {
        SqlDataReader dr = null;
        DataSet ds = new DataSet();
        try
        {
            SqlConnection conn = new SqlConnection(
               ConfigurationManager.ConnectionStrings[
               "StaticDataHelperConnectionString"].ToString());
            SqlCommand cmd = new SqlCommand("proc_StaticDataSelect", conn);

            conn.Open();
            dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

            ds.Load(dr, LoadOption.OverwriteChanges, 
                    GetDataTablesValuesArray());
            return ds;
        }
        finally
        {
            if (dr != null && !dr.IsClosed)
            {
                dr.Close();
            }
        }
    }

Load 方法的第三个参数需要一个表名字符串数组。GetDataTablesValuesArray 方法从 Tables 枚举生成表名字符串数组。

    private static string[] GetDataTablesValuesArray()
    {
        string[] s = new string[0];
        foreach (Tables value in Enum.GetValues(typeof(Tables)))
        {
            Array.Resize(ref s, s.Length + 1);
            s.SetValue(value.ToString(), s.Length - 1);
        }
        return s;
    }

私有属性 StaticDataSet 和公共方法 CacheStaticData 管理 DataSet 的缓存。

    private static DataSet StaticDataSet
    {
        get
        {
            // Get DataSet from Cache

            Cache oCache = System.Web.HttpContext.Current.Cache;
            DataSet ds = (DataSet)oCache[StaticDataSetCache];

            // If DataSet is not in Cache then generate it and cache it

            if (ds == null)
            {
                ds = CacheStaticData();
            }

            return ds;
        }
    }
    
    public static DataSet CacheStaticData()
    {
        Cache oCache = System.Web.HttpContext.Current.Cache;

        // Get Static DataSet

        DataSet ds = GetDataSet();
        // Insert into cache

        oCache.Insert(StaticDataSetCache, ds);

        return ds;
    }

公共方法 Bind 用于从缓存中检索静态数据并将其绑定到 ListControl

    public static void Bind(ListControl listControl, Tables tableIndex)
    {
        Bind(listControl, tableIndex, "");
    }   

    public static void Bind(ListControl listControl, 
           Tables tableIndex, string header)
    {
        // Get the DataTable from the cached DataSet

        DataTable dt = GetData(tableIndex);

        // Set the DataValueField and DataTextField of the LsitControl        

        listControl.DataValueField = dt.Columns[0].ToString();
        listControl.DataTextField = dt.Columns[1].ToString();

        // Bind the data to the LsitControl

        listControl.DataSource = dt;
        listControl.DataBind();

        // Add the header row if required

        if (header.Length > 0)
        {
            listControl.Items.Insert(0, new ListItem("- " + 
                                       header + " -", "0"));
        }
    }

此方法从缓存的 DataSet 中以指定的表索引检索 DataTable。它根据 DataTable 的列名设置 ListControlDataValueFieldDataTextField 属性,然后将 DataTable 绑定到 ListControl
如果传递了 header 字符串参数,它将被插入为顶部的项。

使用限制

此类助手旨在管理静态数据,因此数据会在应用程序的整个生命周期内进行缓存。如果您有允许管理员用户更新查找表的功能,您可以在更新发生时调用 StaticData.CacheStaticData(); 方法来刷新缓存的数据。

对于会频繁更改的数据,您可以使用 Cache.Insert 重载设置过期时间。

oCache.Insert(StaticDataSetCache, ds, null, DateTime.Now.AddMinutes(30), 
              Cache.NoSlidingExpiration);

您也可以设置 SQL Server 2005 的缓存依赖项,但这超出了本文的范围。

关注点

DataSet.Load 方法可以通过 SqlDataReader 将多个结果集从单个存储过程加载到 DataSet 中。缓存此 DataSet 是在 ASP.NET 应用程序中存储多个静态数据表的便捷方法。

历史

  • v1.0 - 2006 年 10 月 21 日
  • v1.1 - 2006 年 10 月 25 日

    在演示中添加了 RadioButtonListCheckBoxList 控件。

  • v1.2 - 2006 年 11 月 2 日
    部分措辞和格式调整。
© . All rights reserved.