ASP.NET 快速入门系列系列--ASP.NET2.0绑定到数据库


绑定到数据库
    要在Web 应用程序中显示的最常见数据类型之一是来自诸如 Microsoft SQL Server、Oracle 等 SQL 数据库或其他 OLEDB 或 ODBC 数据存储区的数据。SqlDataSource 控件在 Web 应用程序中表示到数据库的直接连接,数据绑定控件可使用它自动检索数据。SqlDataSource 旨在替代通常在页中编写以创建连接和命令来查询数据库的 ADO.NET 代码。由于数据查询被直接指定为数据源控件的属性,这有时称为两层模型,因为数据查询仍然在页代码中维护。由于这个原因,SqlDataSource 控件通常针对不需要完全封装的数据中间层对象的小型业余爱好者或个人站点。本教程后面有一个部分将讨论 ObjectDataSource 控件,该控件针对需要数据库查询的中间层封装的较大型企业。

GridView 控件
   为了演示如何绑定数据库中的数据,本节中的示例利用一个新的名为 GridView 的数据绑定控件。GridView 控件是 ASP.NET 2.0 中用于以表格网格格式呈现数据的新的数据绑定控件。网格中的每一行对应于一个数据记录,列表示记录的字段。如果熟悉 ASP.NET 1.x 版中的 DataGrid 控件,则 GridView 是其替代控件,并支持非常相似的对象模型。

GridView 控件支持以下功能:
绑定到数据源控件。
内置的排序功能。
内置的更新和删除功能。
内置的分页功能。
内置的行选择功能。
对 GridView 对象模型进行编程访问以动态设置属性和处理事件。
诸如 CheckBoxField 和 ImageField 等新的列类型。
用于超链接列的多个数据字段。
用于选择、更新和删除的多个数据键字段。
可通过主题和样式自定义的外观。


创建数据报表
最简单的数据驱动页类型是只读报表,它显示数据但不允许用户操作表示形式或修改数据。若要根据 SQL 数据库创建只读报表,需要先在页上配置一个 SqlDataSource,然后通过指定诸如 GridView 这样的数据绑定控件的 DataSourceID 属性将其连接到数据源。下面的示例演示与 SqlDataSource 控件关联的 GridView 控件。


<form runat="server">
  <asp:GridView ID="GridView1" DataSourceID="SqlDataSource1" runat="server"/>
  <asp:SqlDataSource ID="SqlDataSource1" runat="server"
    SelectCommand="SELECT [au_id], [au_lname], [au_fname] FROM [authors]"
    ConnectionString="<%$ ConnectionStrings:Pubs %>" />
</form>

    SqlDataSource 的 ConnectionString 属性指定到数据库的连接字符串,SelectCommand 属性指定要执行以检索数据的查询。连接字符串可以在页中按字面文本指定,不过在此例中,该属性是使用从 Web.config 检索值的新的表达式语法指定的。在下面的示例中,GridView 控件绑定到一个连接到 Microsoft™ SQL Server 数据库的 SqlDataSource 控件。

C# GridView-SqlDataSource
 
 

SqlDataSource 控件并不仅限于连接到 Microsoft™ SQL Server 数据库。它实际上能够连接到被配置为 System.Data.Common.DbProviderFactory 的任何托管 ADO.NET 提供程序。默认情况下,.NET Framework machine.config 中包括四个提供程序:

<configuration>
  <system.data>
    <DbProviderFactories>
      <add name="Odbc Data Provider" invariant="System.Data.Odbc" type="System.Data.Odbc.OdbcFactory, ..." />
      <add name="OleDb Data Provider" invariant="System.Data.OleDb" type="System.Data.OleDb.OleDbFactory, ..." />
      <add name="OracleClient Data Provider" invariant="System.Data.OracleClient" type="System.Data.OracleClient.OracleClientFactory, ..." />
      <add name="SqlClient Data Provider" invariant="System.Data.SqlClient" type="System.Data.SqlClient.SqlClientFactory, ..." />
    </DbProviderFactories>
  </system.data>
</configuration>

SqlDataSource 的 ProviderName 属性可设置为任何有效提供程序工厂的固定名称(默认为 System.Data.SqlClient)。注意,如果更改提供程序名称,则需要确保 ConnectionString 和 SelectCommand 属性使用所选提供程序的正确语法。

在上面的示例中,GridView 控件反映 SqlDataSource 返回的数据记录的字段以动态生成网格的列。通过向 GridView 的 Columns 集合添加 DataControlField 对象,还可以指定要显示的显式列字段。这样允许确切指定要显示的列以及它们的相对顺序。下面的示例演示 GridView 的 Columns 集合中的 BoundField 和 CheckBoxField 对象的集合。可分配给此集合的其他字段类型包括 ImageField、HyperLinkField、CommandField、ButtonField 和 TemplateField。

C# GridView-SqlDataSource (BoundFields)
  

SqlDataSource 的 SelectCommand 属性还可以设置为存储过程名称而不是 SQL 命令文本。若要启用此功能,请将 SelectCommandType 属性设置为“StoredProcedure”。下面的示例演示被配置为从 Northwind 示例数据库中的存储过程选择数据的 SqlDataSource 控件。

C# GridView-SqlDataSource (Stored Procedure)


  

默认情况下,SqlDataSource 控件返回包含查询结果的 DataSet 对象中的 DataView。通过将 SqlDataSourceMode 属性设置为“DataReader”,可以配置 SqlDataSource 控件将数据作为 DataReader 返回。当只需对数据进行仅向前、只读访问时,使用 DataReader 一般比使用 DataSet 具有更好的性能。但是要注意 SqlDataSource 的排序功能在此模式下将被禁用。下面的示例演示 SqlDataSource 的 DataReader 模式。

C# GridView-SqlDataSource (DataReader)


 
 
连接字符串设置

在上面的示例中,SqlDataSource 使用 ASP.NET 2.0 中在运行时解析为连接字符串值的新的声明性表达式语法,按名称引用数据库连接字符串。连接字符串本身存储在 Web.config 文件中的 <connectionStrings> 配置节下面,以便易于在单个位置为应用程序中的所有页维护它。
<configuration>
  <connectionStrings>
    <add name="Pubs" connectionString="Server=(local);Integrated Security=True;Database=pubs;"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

下面的示例显示上面的 SqlDataSource 示例所使用的 Web.config 文件。

 Connection Strings Configuration


 
 

在 Web.config 中存储连接字符串是对任何 ASP.NET 应用程序的建议做法,这样不仅是为了实现集中的管理,而且是为了保护连接字符串。在生产环境中,可以使用 ASP.NET 2.0 中的一个命令行工具加密此节以实现进一步的安全性。有关加密连接字符串的更多详细信息,请参考本教程的管理部分中的“加密配置节”主题。下一个示例显示具有加密的 <connectionStrings/> 节的 Web.config 文件。

Connection Strings Configuration (Encrypted)


 
然后 SqlDataSource 控件的 ConnectionString 属性被设置为表达式 <%$ ConnectionStrings:Pubs %>,该表达式在运行时由 ASP.NET 分析器解析为连接字符串。还可以为 SqlDataSource 的 ProviderName 属性指定一个表达式,例如 <%$ ConnectionStrings:Pubs.ProviderName %>。

数据排序和分页
GridView 控件相对于其他数据绑定控件的关键优点之一是其自动利用数据源功能的能力。与依赖页代码对数据进行手动排序和分页不同,GridView 控件能够自动执行这些操作 -- 只要将数据源配置为支持这些操作。

SqlDataSource 控件在其 DataSourceMode 属性设置为“DataSet”时支持排序。若要在 GridView 中启用排序 UI,请将 AllowSorting 属性设置为 true。这导致 GridView 呈现其列标题的链接按钮,可单击这些按钮对列进行排序。GridView 控件将与列字段关联的 SortExpression 传递给数据源控件,后者向 GridView 返回排序的数据。

SqlDataSource 预期的 SortExpression 语法与 System.Data.DataView 的 Sort 属性的语法相同,虽然其他数据源可能支持不同的语法。由于 SqlDataSource 的排序行为依赖基础的 DataView Sort 属性,SqlDataSource 仅在 DataSet 模式下支持排序;如果设置为 DataReader 模式,则排序将被禁用。 SortExpression 通常被设置为与 GridView 的某列关联的单个字段名称。GridView 在每次单击时自动交替向 SortExpression 追加“ASC”或“DESC”,以便在升序和降序排序顺序之间切换。

C# GridView Sorting


 

通过将 AllowPaging 属性设置为 true,还可以在 GridView 中启用分页 UI。GridView 能够对从数据源返回的任何支持 ICollection 接口的值自动进行分页。当 SqlDataSource 处于 DataSet 模式时返回的 DataView 支持此接口,因此 GridView 能够对结果分页。当处于 DataReader 模式时,GridView 不能对 SqlDataSource 返回的数据分页。下面的示例基于 DataSet 模式下的 SqlDataSource 演示了 GridView 分页 UI。

C# GridView Paging

 
 

通过分别配置 PagerStyle 和 PagerSettings 属性,还可以自定义页导航的样式和设置。PagerStyle 确定页导航的外观和风格,而 PagerSettings 确定要使用的分页的类型(数字或“Next/Previous”(下一页/上一页)按钮)、页导航位置和相关选项。下面的示例演示其中一些应用于 GridView 页导航的样式和设置。

C# GridView Pager Settings

 
 
注意,上面的示例中的分页操作完全是由 GridView 控件对支持 ICollection 接口的 SqlDataSource 返回的 DataView 执行的。在此例中,GridView 从数据源检索所有数据记录,呈现行的一个子集,然后丢弃其余的行。这有时称为“UI 分页”,因为分页逻辑发生在 GridView 控件的呈现层中。虽然便于对任意集合分页,但这不一定是对数据分页的最有效方式。还可以在数据源接口级别配置分页,以便 GridView 仅从数据源请求呈现当前页所需要的行数。SqlDataSource 控件目前不支持接口级别的分页。ObjectDataSource 控件支持此功能,并将在本教程的“高级排序和分页”主题中讨论。
更新和删除数据
就像排序和分页一样,通过 Update 和 Delete 操作,GridView 控件还能够自动呈现用于修改数据的 UI -- 只要关联的数据源被配置为支持这些功能。SqlDataSource 控件在其 UpdateCommand 和 DeleteCommand 属性分别设置为有效的更新或删除命令或存储过程时分别支持 Update 操作和 Delete 操作。UpdateCommand 或 DeleteCommand 应该包含用于 GridView 控件将传递的每个值的参数占位符(下面还会讨论关于这点的更多信息)。还可以指定一个 UpdateParameters 或 DeleteParameters 集合以设置每个参数的属性,例如参数数据类型、输入/输出方向或默认值。随后的主题将更详细地讨论这些集合。


<asp:SqlDataSource ID="SqlDataSource1" runat="server"
  ConnectionString="<%$ ConnectionStrings:Pubs %>"
  SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors]"
  UpdateCommand="UPDATE [authors] SET [au_lname] = @au_lname, [au_fname] = @au_fname, [state] = @state WHERE [au_id] = @au_id"
  DeleteCommand="DELETE FROM [authors] WHERE [au_id] = @au_id"/>

为了在 GridView 中启用用于 Update 或 Delete 的 UI,可以将 AutoGenerateEditButton 和 AutoGenerateDeleteButton 属性设置为 true,或者可以向 GridView 控件添加一个 CommandField 并启用其 ShowEditButton 和 ShowDeleteButton 属性。GridView 支持一次编辑或删除一行。对于编辑,用户通过单击“Edit”(编辑)按钮将行置于编辑模式,然后在该行处于编辑模式时单击“Update”(更新)按钮确认 Update。用户还可以单击“Cancel”(取消)按钮中止编辑操作并返回只读模式。下面的示例演示配置用于更新数据行的 GridView 和 SqlDataSource。

C# GridView Updating


 
在 Update 和 Delete 操作中扮演特殊角色的一个重要属性是 DataKeyNames 属性。此属性通常被设置为数据源中字段的名称,这些字段是用于匹配该数据源中的给定行的主键的一部分。当以声明方式指定此属性时,多个键之间用逗号分隔,虽然通常只有一个主键字段。为了保留原始值以传递给 Update 或 Delete 操作,DataKeyNames 属性指定的字段的值在视图状态中往返,即使该字段并未作为 GridView 控件中的列之一被呈现。当 GridView 调用数据源 Update 或 Delete 操作时,它在一个特殊的 Keys 字典中将这些字段的值传递给数据源,该字典独立于包含用户在行处于编辑模式时(对于更新操作)输入的新值的 Values 字典。 Values 字典的内容是从为处于编辑模式的行呈现的输入控件中获得的。若要排除此字典中的某个值,请将 Columns 集合中的对应 BoundField 的 ReadOnly 属性设置为 true。如果在 Visual Studio 中使用 GridView 设计器,则主键字段的 ReadOnly 属性默认设置为 true。

请注意分配给 UpdateCommand 的 Update 语句中的参数的命名约定。GridView 和其他数据绑定控件调用 Update 操作的自动功能需依赖此命名约定才能工作。参数的命名预期应与 SelectCommand 返回的关联字段值相同。使用此命名约定使得数据绑定控件传递给数据源的值与 SQL Update 语句中的参数相对应成为可能。

此默认命名约定的使用假设 Keys 和 Values 字典的内容相互排斥 -- 即用户能够在数据绑定控件处于编辑模式时更新的字段值的命名应该与用于匹配要更新的行的字段值(对于 SqlDataSource,这些字段值在 WHERE 子句中)的命名不同。考虑这点的另一种方式是在 DataKeyNames 上设置的任何字段都应该设置为只读或在数据绑定控件中(例如在 GridView Columns 集合中)不可见。

虽然键字段为只读的情况很普遍,但是存在一些有效的方案,其中您将希望能够更新同时还用于匹配要更新的数据行的字段。例如,如果在 GridView 的 Columns 集合中的一个也在 DataKeyNames 中被设置的字段上设置 ReadOnly=false,则 GridView 将在 Keys 字典中传递该字段的旧值,而在 Values 字典中传递该字段的新值。为了区别这两类值,需要在 SQL 语句中以不同的方式命名参数,例如:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
  ConnectionString="<%$ ConnectionStrings:Pubs %>"
  SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors]"
  UpdateCommand="UPDATE [authors] SET [au_id] = @au_id, [au_lname] = @au_lname, [au_fname] = @au_fname, [state] = @state WHERE [au_id] = @original_au_id"
  DeleteCommand="DELETE FROM [authors] WHERE [au_id] = @original_au_id"/>
  OldValuesParameterFormatString="original_{0}"

在此示例中,参数名称 @original_au_id 用于引用键字段的原始值,@au_id 用于引用新值。SqlDataSource 的 OldValuesParameterFormatString 属性也被设置为有效的 .NET Framwork 格式字符串,以指示应该如何重命名 Keys 字典中的参数。当 SqlDataSource 的 ConflictDetection 属性设置为 CompareAllValues 时,此格式字符串还应用于数据绑定控件传递的非键字段的旧值。对于 Delete 操作,SqlDataSource 默认仅应用 Keys 字典(不存在用于删除操作的新值),并使用 OldValuesParameterFormatString 属性的值格式化键参数名称。


筛选数据
数据驱动页中的一种常见方案是筛选报表中的数据的能力。例如,假设用户可以从 DropDownList 中的一组字段值中选择以筛选报表网格,从而仅显示具有匹配字段值的行。在 ASP.NET 1.x 版中,将需要在代码中执行以下步骤:
如果请求是回发,则在 Page_Load 中取消数据绑定
处理 SelectedIndexChanged 事件
向命令的 Parameters 集合添加 DropDownList SelectedValue
执行该命令并调用 DataBind
在 ASP.NET 2.0 中,由于使用了声明性“数据参数”对象,因此不再使用此代码。数据参数允许将外部值以声明方式与数据源操作关联。这些参数通常与命令表达式或属性中的变量关联,例如 SQL 语句中的参数或 SqlDataSource 的存储过程。数据源控件公开参数集合属性,这些属性可以包含每个受支持的数据操作的参数对象。例如:
<asp:DropDownList ID="DropDownList1" ... runat="server"/>
...
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
  ConnectionString="<%$ ConnectionStrings:Pubs %>"
  SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors] WHERE [state] = @state">
  <SelectParameters>
    <asp:ControlParameter Name="state" ControlID="DropDownList1" PropertyName="SelectedValue" />
  </SelectParameters>
</asp:SqlDataSource>

下面的示例演示用于从请求 URL 的 Querystring 中获得参数值的 QueryStringParameter:


C# Filter By QueryString
 

下一个示例演示用于从页上的 DropDownList 控件中获得参数值的 ControlParameter:

C# Filter By DropDownList


 
可以配置数据参数以便从以下任意来源检索值:

名称 说明
   Parameter Parameter 类是派生其他所有 Parameter 类型的公共基类。Parameter 类还作为静态参数的实现,其中值是使用 DefaultValue 属性静态指定的。

Parameter 共享一个公共的 Name 属性,该属性是特定数据源操作的参数名称(例如,这将匹配 SqlDataSource 的 SelectCommand 中的参数名称)。所有 Parameter 还共享一个 Type 属性,该属性指定参数值的类型。

Parameter 还共享一个 Direction 属性,该属性用于指定 Parameter 是用于 Input、Output(或 ReturnValue)还是同时用于 Input 和 Output。数据源一般从传递给数据源操作的状态事件的事件参数公开输出参数和返回值。有关示例,请参考本教程的 处理参数 主题。 
   QueryStringParameter QueryStringParameter 类将 querystring 字段的值绑定到 Parameter 对象的值。QueryStringField 属性与从中检索值的 querystring 字段的名称相匹配。DefaultValue 属性将在 querystring 值不可用的任何时候返回。 
   ControlParameter ControlParameter 类将 Control 属性的值绑定到 Parameter 对象的值。ControlID 属性与其属性被绑定到该参数的 Control 的 ID 相匹配。PropertyName 指定从中检索实际值的控件的属性。由 ControlID 指定其 ID 的 Control 能够可选地定义 ControlValuePropertyAttribute,该属性确定要从中检索控件的值的默认属性名称。此属性将在未显式设置 PropertyName 的任何时候使用。ControlValuePropertyAttribute 应用于以下控件属性:
Label.Text
TextBox.Text
ListControl.SelectedValue(例如 DropDownList)
CheckBox.Checked
Calendar.SelectedDate
DetailsView.SelectedValue
GridView.SelectedValue
TreeView.SelectedValue
FileUpload.FileBytes
 
   SessionParameter SessionParameter 类将 Session 对象的值绑定到 Parameter 对象的值。SessionField 属性与从中检索值的 Session 键的名称相匹配。DefaultValue 属性将在 Session 值不可用的任何时候返回。 
   FormParameter FormParameter 类将 HTML 窗体字段的值绑定到 Parameter 对象的值。FormField 属性与从中检索值的窗体字段的名称相匹配。DefaultValue 属性将在 Form 值不可用的任何时候返回。 
   CookieParameter CookieParameter 类将 HttpCookie 的值绑定到 Parameter 对象的值。CookieName 属性与从中检索值的 Cookie 的名称相匹配(仅支持简单值 Cookie)。DefaultValue 属性将在 Cookie 值不可用的任何时候返回。 
   ProfileParameter ProfileParameter 类将 User Profile 对象的值绑定到 Parameter 对象的值。ParameterName 属性与从中检索值的配置文件属性的名称相匹配。DefaultValue 属性将在该属性值不可用的任何时候返回。有关更多信息,请参考本教程的“用户配置文件”部分。 

注意根据外部源(Control、QueryString,等等)进行求值的数据参数与上面的示例中为 Update、Insert 和 Delete 操作传递的参数之间的区别。在后一种情况下,参数值由调用 Update 操作的数据绑定控件动态提供,在此例中为 GridView 控件。对于 Update、Insert 和 Delete 操作,通常不需要与外部值关联的数据参数。但是,可以在数据源的 UpdateParameters、InsertParameters 或 DeleteParameters 集合中包括 <asp:Parameter> 对象(所有数据参数的基类),以指定将诸如 Type、Direction 或 DefaultValue(在 GridView 传递的值为空时使用的值)等属性应用于从 GridView 控件传递的参数值。
缓存数据
数据源控件的另一个功能是自动缓存数据的能力。尽管仍然可以使用缓存 API 以编程方式缓存数据,但是设置数据源控件的一些声明性属性可以达到相同的结果。若要对 SqlDataSource 控件(以及稍后将讨论的 ObjectDataSource)启用缓存,请将 EnableCaching 属性设置为 true。可以使用 CacheDuration 属性指定要在缓存中存储项的时间长度(以秒为单位)。还可以将 CacheExpirationPolicy 属性设置为 Sliding 或 Absolute,就像能够从缓存 API 中所做的那样。当 DataSourceMode 属性设置为“DataSet”时,缓存仅在 SqlDataSource 控件上受支持。

例如,如果将 CacheDuration 设置为 5,将 SlidingExpiration 设置为 Absolute,SqlDataSource 将在第一次请求该页时从数据库检索数据,并将该数据存储在缓存中。对于后续的请求,SqlDataSource 将尝试检索缓存项以满足该请求而不返回到原始数据库。在 5 秒之后(如果缓存内存压力很高,或许会更早),该缓存项将被清除,对该页的后续请求将导致 SqlDataSource 再次返回数据库(使用新数据重复该缓存过程)。

如果将 CacheDuration 设置为 5,将 SlidingExpiration 设置为 Sliding,则只要数据源每 5 秒请求一次缓存的数据,缓存的数据就将定期刷新其生存时间。如果某个页至少每 5 秒请求一次缓存的数据,并且不存在缓存内存压力,则缓存的数据就会永远有效地保留在缓存中。另一方面,如果 5 秒钟时段内没有针对缓存的数据的请求,则缓存的项将被清除,在下一次出现请求时,SqlDataSource 控件将再次返回原始数据库。

下面的示例演示如何使用 SqlDataSource 控件进行缓存。TimeStamp 列在每次执行查询时更新,因此您可以比较从数据库检索数据与从缓存检索数据的频率。注意,TimeStamp 大约每五秒更新一次。


C# SqlDataSource Caching
 

细心的观察者可能已经注意到,TimeStamp 还会在每次为页上的 DropDownlist 筛选器选择一个新值时更新。其原因在于,提供给 SelectCommand 的每组唯一的参数都导致对数据库的不同查询,从而在缓存中产生一个单独的项(注意,如果在 5 秒的时间段内两次选择 DropDownList 中的同一值,则该参数值的 TimeStamp 是相同的)。

一种很适合较小的数据查询的替代方法是最初从数据库选择所有数据放在缓存中,然后针对不同的参数值筛选单个缓存项。为了支持此方案,SqlDataSource 控件支持一个 FilterExpression 属性和对应的 FilterParameters 集合。与向命令本身应用参数值(SelectParameters 就是这样)不同,筛选表达式应用于通过执行该命令返回的 DataView 对象的 RowFilter 属性。该表达式语法必须与 DataView Row Filter 属性的预期语法匹配。

可以使用标准的 .NET Framework 格式字符串语法(例如“{0}”、“{1}”,等等)将参数值的占位符插入 FilterExpression。在运行时,SqlDataSource 控件将 FilterParameters 集合中指定的参数的值应用于 FilterExpression,方法是使用那些值对字符串进行格式设置。注意,参数值是未转义的,因此对于 String 类型,需要将参数占位符括在单引号中。
<asp:DropDownList ID="DropDownList1" ... runat="server"/>
...
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
  ConnectionString="<%$ ConnectionStrings:Pubs %>"
  SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors]">
  FilterExpression="state = '{0}'"
  <FilterParameters>
    <asp:ControlParameter Name="state" ControlID="DropDownList1" PropertyName="SelectedValue" />
  </FilterParameters>
</asp:SqlDataSource>

下面的示例演示此项筛选技术的运行情况。


C# Filtering Cache Entries
 

缓存数据始终是性能(不必在每次请求时返回数据库)和陈旧数据(因为缓存项包含在特定时间捕获的数据的快照)之间的权衡。页经常使用相对较低的 CacheDuration 值以确保缓存数据相当的新。更理想的情况是仅当数据库中的基础数据更改时才使缓存项失效。只要数据未更改,就没有理由清除缓存项。

ASP.NET 2.0 中的一个称为 SQL Cache Invalidation 的新功能允许配置数据源无限期地(或在指定的持续时间内)缓存数据,直至数据库中的数据更改,届时缓存项将被清除。此项技术允许使用更高的 CacheDuration 值,同时仍然保证显示的数据始终与数据库中的值匹配。 SQL Cache Invalidation 仅在 Microsoft™ SQL Server 数据库上受支持。存在两种 SQL Cache Invalidation 实现:SQL Server 2005 上支持的基于通知的实现和早期版本的 SQL Server 上支持的基于轮询的实现。本教程的 SQL Cache Invalidation 部分将描述配置这其中任一种实现所需要的步骤。

一旦配置了 SQL Cache Invalidation,就可以通过指定数据源的 SqlCacheDependency 属性从数据源控件中使用它。如果使用基于轮询的实现,则该值接受 connectionName:tableName 形式的格式。如果使用基于通知的实现,则将此属性设置为“CommandNotification”。

在下一个示例中,CacheDuration 被设置为“Infinite”,并且指定了 SqlCacheDependency。注意,TimeStamp 列在使用 GridView 上的“编辑” 按钮修改数据之前不会更新。


C# Data Source SqlCacheInvalidation
 
主/详细信息和 DetailsView 控件
我们在“筛选数据”节中看到了数据源控件如何能够接受来自外部源的参数值,例如窗体上的其他控件、querystring 值,等等。可采用类似的技术来构建主/详细信息方案。主/详细信息通常是指这样一种控件安排,其中一个控件(“主”控件)中的选定记录在另一个控件(“详细信息”控件)中显示选定记录的附加详细信息。附加详细信息可以是同一数据项的属性,或者是通过数据库中的外键关系与主数据项关联的相关记录。

GridView 控件支持一个 SelectedValue 属性,该属性指示 GridView 中当前选择的行。SelectedValue 属性求值为 DataKeyNames 属性中指定的第一个字段的值。通过将 AutoGenerateSelectButton 设置为 true,或者通过向 GridView Columns 集合添加 ShowSelectButton 设置为 true 的 CommandField,可以启用用于 GridView 上的选择的 UI。然后 GridView 的 SelectedValue 属性可以与数据源中的 ControlParameter 关联以用于查询详细信息记录,与上面的示例中为 DropDownList 配置筛选的方法大致相同。

若要显示当前选择的行的详细信息,应该使用另一个 GridView 控件,不过 ASP.NET 还包含一个唯一适合此目的的新的 DetailsView 控件。该 DetailsView 控件一次呈现单个记录而不是记录的集合。像 GridView 一样,DetailsView 以表格格式呈现,只不过各行对应于每个数据字段(就像 GridView 列)。字段在 DetailsView 的 Fields 集合中指定。 DetailsView 还可以选择以与 GridView 分页相同的方式对记录的集合分页(在 DetailsView 中,PageSize 始终为 1)。


C# Master-Details w/ GridView and DetailsView
 

 

DetailsView 像 GridView 一样支持编辑,您可以使用 AutoGenerateEditButton 或 CommandField.ShowEditButton 属性以同样的方式启用该 UI。当然,与 DetailsView 关联的数据源还必须配置为支持 Update 操作(这里通过在 SqlDataSource 上指定 UpdateCommand 实现)。下面的示例演示一个被配置为支持在主/详细信息方案中编辑记录的 DetailsView。


C# DetailsView Editing
 

每当数据源发生更改后(例如更新后),数据绑定控件通常都会自动重新绑定到其数据源。但是,在前面的示例中,DetailsView 绑定到 GridView 外的其他数据源,因此,当调用 Update 操作时,只有 DetailsView 会从其数据源接收更改事件。若要强制 GridView 在 DetailsView 执行更新时也进行重新绑定,可在 DetailsView ItemUpdated 事件中对 GridView 显式调用 DataBind()。此示例还处理事件,以在出现 GridView 排序或分页操作或在 DropDownList 控件中选择了新的筛选器值时禁用编辑。

在 Web 应用程序中将主/详细信息显示拆分到若干页上是很常见的。为此,可以向 GridView 的每一行添加超链接以导航到单独的详细信息页,并与 querystring 一起传递参数。在详细信息页中,绑定到 DetailsView 的数据源将使用 QueryStringParameter 对象接受这些参数。

可以通过向 GridView 的 Columns 集合添加 HyperLinkField 对象来添加超链接。HyperLinkField 的 Text 属性设置要为超链接显示的文本(例如“查看详细信息…”),而 NavigateUrl 属性则指定要在链接被单击时导航的 URL。不必为所有行指定静态 URL,更为普遍的是指定要在动态 URL 的构造中使用的 NavigateUrlFields。可以声明方式将 NavigateUrlFields 设置为数据源中的字段的逗号分隔的列表。NavigateUrlFormatString 属性指定用于 URL 的标准 .NET Framework 格式字符串,并使用像 {0} 和 {1} 这样的占位符在运行时替换字段值。

下一个示例通过在不同的页中使用 GridView 和 DetailsView 演示了一个主/详细信息方案。上一个示例演示绑定到相同类型的记录(作者)的 GridView 和 DetailsView,与上一个示例不同,此示例为主控件和详细信息控件显示不同类型的记录(作者和书籍),这些记录由基础表中的外键关系进行关联。因为一个作者记录可能具有多个关联的书籍,DetailsView 已被配置为支持对详细信息页中的书籍记录进行分页。

 
C# Master-Details (Separate Pages)
 
插入数据
与 GridView 控件相似,DetailsView 控件支持通过数据源更新和删除数据。但是,DetailsView 还支持插入数据,而 GridView 不支持。可以轻松地将 DetailsView 和 GridView 配对,以使插入的记录显示在 GridView 控件中。

若要使 SqlDataSource 支持 Insert,请将 InsertCommand 属性设置为有效的插入命令,其中带有 DetailsView 控件在 Insert 模式下呈现的每个字段值的参数占位符。还可以选择指定一个 InsertParameters 集合来包含用于此操作的数据参数对象。

若要启用用于插入的 UI,请将 AutoGenerateInsertButton 属性设置为 true 或向 DetailsView Fields 集合添加 ShowInsertButton 设置为 true 的 CommandField。若要将 DetailsView 置于插入模式,请单击“New”(新建)按钮。当处于插入模式时,DetailsView 将呈现每个字段的输入控件。注意,标记为 ReadOnly 的字段在 Insert 模式下被呈现为输入控件(虽然它们在 Update 模式下不会被呈现为输入控件)。若要从 Insert 模式排除某一字段,请将该字段的 InsertVisible 属性设置为 false。若要提交插入操作,请在插入模式下单击“Insert”(插入)按钮。若要中止插入操作,请单击“Cancel”(取消)按钮。

当 Insert 操作被提交时,DetailsView 从其输入控件收集值,并填充一个 Values 字典以传递给数据源。SqlDataSource 在执行命令之前将这些值应用于 InsertCommand 的参数集合。与 Update 一样,自动插入功能依赖于 InsertCommand 中名称与从选择操作返回的字段完全相同的参数。注意,Insert 不需要 Keys 字典。

 
c# Master-Details Insert
 

可以将 DetailsView 放在单独的页上以执行 Insert 或 Update 操作。下面的示例演示在单独的页上为 Insert 和 Update 操作配置的 DetailsView。注意,在本示例中 DefaultMode 属性设置为 Insert 或 Edit,这样 DetailsView 最初将以此模式呈现,而不是以只读模式呈现。执行 Insert 或 Update 操作后,DetailsView 总是还原为 DefaultMode(默认情况下为 ReadOnly)。

 
c# Master-Details Insert (Separate Pages)
  
 

 

posted @ 2006-03-10 09:30  启明星工作室  阅读(7674)  评论(1编辑  收藏  举报