Microsoft

ASP.NET 1.x 中的 DataGrid 控件在 Web 应用程序中的数据访问方面有了很大的改进。 但是,它并不像以前那样用户友好。 它仍然需要大量的代码才能从中获取有用的功能。 这是 1.x 中所有数据访问工作中的模型。

ASP.NET 1.x 中的 DataGrid 控件在 Web 应用程序中的数据访问方面有了很大的改进。 但是,它并不像以前那样用户友好。 它仍然需要大量的代码才能从中获取有用的功能。 这是 1.x 中所有数据访问工作中的模型。

ASP.NET 2.0 通过部分数据源控件解决此问题。 ASP.NET 2.0 中的数据源控件为开发人员提供了用于检索数据、显示数据和编辑数据的声明性模型。 数据源控件的目的是向数据绑定控件提供一致的数据表示形式,而不考虑这些数据的来源。 ASP.NET 2.0 中数据源控件的核心是 DataSourceControl 抽象类。 DataSourceControl 类提供 IDataSource 接口和 IListSource 接口的基本实现,后者允许你通过稍后) 讨论的新 DataSourceId 属性,将数据源控件分配为数据绑定控件的 DataSource (,并将其中的数据公开为列表。 数据源控件中的每个数据列表都作为 DataSourceView 对象公开。 对 DataSourceView 实例的访问权限由 IDataSource 接口提供。 例如,GetViewNames 方法返回一个 ICollection,该 ICollection 允许枚举与特定数据源控件关联的 DataSourceView,而 GetView 方法允许按名称访问特定的 DataSourceView 实例。

数据源控件没有用户界面。 它们作为服务器控件实现,以便它们可以支持声明性语法,并根据需要访问页面状态。 数据源控件不会向客户端呈现任何 HTML 标记。

稍后将看到,使用数据源控件还可以获得缓存优势。

存储连接字符串

在开始研究如何配置数据源控件之前,应介绍 ASP.NET 2.0 中有关连接字符串的新功能。 ASP.NET 2.0 在配置文件中引入了一个新部分,使你可以轻松地存储可在运行时动态读取的连接字符串。 使用 <connectionStrings> 部分可以轻松存储连接字符串。

以下代码片段添加新的连接字符串。

<connectionStrings> <add name="Northwind" connectionString="Data Source=localhost; Integrated Security=SSPI;Initial Catalog=Northwind;" providerName="System.Data.SqlClient" /> </connectionStrings>

与 appSettings> 部分一样,<connectionStrings> 部分显示在配置文件的 system.web> 节之外<。<

若要使用此连接字符串,可以在设置服务器控件的 ConnectionString 属性时使用以下语法。

ConnectionString="<%$ ConnectionStrings:Northwind%>"

<connectionStrings> 节也可以加密,以便不会公开敏感信息。 此功能将在后面的模块中介绍。

缓存数据源

每个 DataSourceControl 提供四个属性用于配置缓存;EnableCaching、CacheDuration、CacheExpirationPolicy 和 CacheKeyDependency。

EnableCaching

EnableCaching 是一个布尔属性,用于确定是否为数据源控件启用缓存。

CacheDuration 属性

CacheDuration 属性设置缓存保持有效的秒数。 将此属性设置为 0 会导致缓存在显式失效之前保持有效。

CacheExpirationPolicy 属性

CacheExpirationPolicy 属性可以设置为 AbsoluteSliding。 将其设置为 Absolute 意味着缓存数据的最大时间量是 CacheDuration 属性指定的秒数。 通过将它设置为“滑动”,当执行每个操作时,过期时间将重置。

CacheKeyDependency 属性

如果为 CacheKeyDependency 属性指定了字符串值,ASP.NET 将基于该字符串设置新的缓存依赖项。 这样,只需更改或删除 CacheKeyDependency 即可使缓存显式失效。

重要说明:如果启用了模拟,并且对数据源和/或数据内容的访问基于客户端标识,则建议通过将 EnableCaching 设置为 False 来禁用缓存。 如果在此方案中启用了缓存,并且最初请求数据的用户以外的用户发出请求,则不会强制执行对数据源的授权。 数据将仅从缓存中提供。

SqlDataSource 控件

SqlDataSource 控件允许开发人员访问存储在任何支持 ADO.NET 的关系数据库中的数据。 它可以使用 System.Data.SqlClient 提供程序访问SQL Server数据库、System.Data.OleDb 提供程序、System.Data.Odbc 提供程序或 System.Data.OracleClient 提供程序来访问 Oracle。 因此,SqlDataSource 当然不仅用于访问SQL Server数据库中的数据。

若要使用 SqlDataSource,只需为 ConnectionString 属性提供值,并指定 SQL 命令或存储过程。 SqlDataSource 控件负责处理底层 ADO.NET 体系结构。 它会打开连接,查询数据源或执行存储过程,返回数据,然后关闭连接。

由于 DataSourceControl 类会自动关闭连接,因此它应减少因泄漏数据库连接而生成的客户呼叫数。

下面的代码片段使用存储在配置文件中的连接字符串将 DropDownList 控件绑定到 SqlDataSource 控件,如下所示。

<asp:SqlDataSource id="SqlDataSource1" runat="server" DataSourceMode="DataReader" ConnectionString="<%$ ConnectionStrings:Northwind%>" SelectCommand="SELECT EmployeeID, LastName FROM Employees"> </asp:SqlDataSource><asp:DropDownList id="ListBox1" runat="server" DataTextField="LastName" DataValueField="EmployeeID" DataSourceID="SqlDataSource1"> </asp:DropDownList>

如上所述,SqlDataSource 的 DataSourceMode 属性指定数据源的模式。 在上面的示例中,DataSourceMode 设置为 DataReader。 在这种情况下,SqlDataSource 将使用仅向前和只读游标返回 IDataReader 对象。 返回的指定类型的对象由所使用的提供程序控制。 在本例中,我使用的是 web.config 文件的 connectionStrings> 节中指定的 <System.Data.SqlClient 提供程序。 因此,返回的对象的类型为 SqlDataReader。 通过指定 DataSourceMode 值 DataSet,可将数据存储在服务器上的 DataSet 中。 此模式允许你添加排序、分页等功能。如果我将 SqlDataSource 数据绑定到 GridView 控件,我会选择 DataSet 模式。 但是,对于 DropDownList,DataReader 模式是正确的选择。

缓存 SqlDataSource 或 AccessDataSource 时,DataSourceMode 属性必须设置为 DataSet。 如果使用 DataReader 的 DataSourceMode 启用缓存,则会发生异常。

SqlDataSource 属性

下面是 SqlDataSource 控件的一些属性。

CancelSelectOnNullParameter

一个布尔值,指定如果其中一个参数为 null,则选择命令是否取消。 默认值为 True。

ConflictDetection

如果多个用户可能同时更新数据源,则 ConflictDetection 属性确定 SqlDataSource 控件的行为。 此属性的计算结果为 ConflictOptions 枚举的值之一。 这些值为 CompareAllValuesOverwriteChanges。 如果设置为 OverwriteChanges,最后一个将数据写入数据源的人员将覆盖以前的任何更改。 但是,如果 ConflictDetection 属性设置为 CompareAllValues,则会为 SelectCommand 返回的列创建参数,并且还会创建参数来保存其中每个列中的原始值,使 SqlDataSource 能够确定自执行 SelectCommand 以来值是否发生了更改。

DeleteCommand

设置或获取从数据库中删除行时使用的 SQL 字符串。 这可以是 SQL 查询或存储过程名称。

DeleteCommandType

设置或获取 delete 命令的类型,无论是 SQL 查询 (Text) ,还是存储过程 (StoredProcedure) 。

DeleteParameters

返回与 SqlDataSource 控件关联的 SqlDataSourceView 对象的 DeleteCommand 所使用的参数。

OldValuesParameterFormatString

如果 ConflictDetection 属性设置为 CompareAllValues,则此属性用于指定原始值参数的格式。 默认值为 {0} ,这意味着原始值参数将采用与原始参数相同的名称。 换句话说,如果字段名称为 EmployeeID,则原始值参数为 @EmployeeID。

SelectCommand

设置或获取用于从数据库检索数据的 SQL 字符串。 这可以是 SQL 查询或存储过程名称。

SelectCommandType

设置或获取 select 命令的类型,可以是 SQL 查询 (Text) ,也可以是 storedProcedure) (存储过程。

SelectParameters

返回与 SqlDataSource 控件关联的 SqlDataSourceView 对象的 SelectCommand 所使用的参数。

SortParameterName

获取或设置对数据源控件检索的数据进行排序时使用的存储过程参数的名称。 仅当 SelectCommandType 设置为 StoredProcedure 时有效。

SqlCacheDependency

指定SQL Server缓存依赖项中使用的数据库和表的分号分隔字符串。 (SQL 缓存依赖项将在后面的模块中讨论。)

UpdateCommand

设置或获取更新数据库中的数据时使用的 SQL 字符串。 这可以是 SQL 查询或存储过程名称。

UpdateCommandType

设置或获取更新命令的类型,可以是 SQL 查询 (Text) ,也可以是 StoredProcedure) (存储过程。

UpdateParameters

返回由与 SqlDataSource 控件关联的 SqlDataSourceView 对象的 UpdateCommand 使用的参数。

AccessDataSource 控件

AccessDataSource 控件派生自 SqlDataSource 类,用于将数据绑定到 Microsoft Access 数据库。 AccessDataSource 控件的 ConnectionString 属性是只读属性。 DataFile 属性用于指向 Access 数据库,而不是使用 ConnectionString 属性,如下所示。

<asp:AccessDataSource id="AccessDataSource1" runat="server" DataFile="~/App_Data/Northwind.mdb"> </asp:AccessDataSource>

AccessDataSource 始终将基础 SqlDataSource 的 ProviderName 设置为 System.Data.OleDb,并使用 Microsoft.Jet.OLEDB.4.0 OLE DB 访问接口连接到数据库。 不能使用 AccessDataSource 控件连接到受密码保护的 Access 数据库。 如果必须连接到受密码保护的数据库,则应使用 SqlDataSource 控件。

存储在网站中的 Access 数据库应放置在 App_Data 目录中。 ASP.NET 不允许浏览此目录中的文件。 使用 Access 数据库时,需要向进程帐户授予对 App_Data 目录的读取和写入权限。

XmlDataSource 控件

XmlDataSource 用于将 XML 数据绑定到数据绑定控件。 可以使用 DataFile 属性绑定到 XML 文件,也可以使用 Data 属性绑定到 XML 字符串。 XmlDataSource 将 XML 属性公开为可绑定字段。 如果需要绑定到未表示为属性的值,则需要使用 XSL 转换。 还可以使用 XPath 表达式筛选 XML 数据。

请考虑以下 XML 文件:

<?xml version="1.0" encoding="utf-8" ?> <People> <Person FirstName="Jake" LastName="Stone"> <Address> <Street>345 Maple St.</Street> <City>Redmond</City> <Region>WA</Region> <ZipCode>01434</ZipCode> </Address> <Job> <Title>CEO</Title> <Description>Develops company strategies.</Description> </Job> </Person> <Person FirstName="Jacob" LastName="Ladder"> <Address> <Street>123 Elm St.</Street> <City>Seattle</City> <Region>WA</Region> <ZipCode>11223</ZipCode> </Address> <Job> <Title>Attorney</Title> <Description>Reviews legal issues.</Description> </Job> </Person> <Person FirstName="Angela" LastName="Hound"> <Address> <Street>34 Palm Avenue</Street> <City>Renton</City> <Region>WA</Region> <ZipCode>63910</ZipCode> </Address> <Job> <Title>IT Director</Title> <Description>In charge of corporate network.</Description> </Job> </Person> </People>

请注意,XmlDataSource 使用 人员/Person 的 XPath 属性,以便仅<筛选 Person> 节点。 然后,DropDownList 使用 DataTextField 属性将数据绑定到 LastName 属性。

虽然 XmlDataSource 控件主要用于将数据绑定到只读 XML 数据,但可以编辑 XML 数据文件。 请注意,在这种情况下,XML 文件中信息的自动插入、更新和删除不会像自动插入、更新和删除其他数据源控件那样自动发生。 相反,您必须编写代码以使用 XmlDataSource 控件的以下方法手动编辑数据。

GetXmlDocument

检索包含 XmlDataSource 检索的 XML 代码的 XmlDocument 对象。

将内存中的 XmlDocument 保存回数据源。

请务必注意,仅当满足以下两个条件时,Save 方法才起作用:

  • XmlDataSource 使用 DataFile 属性绑定到 XML 文件,而不是使用 Data 属性绑定到内存中的 XML 数据。
  • 未通过 Transform 或 TransformFile 属性指定转换。
  • 另请注意,当多个用户同时调用 Save 方法时,可能会产生意外的结果。

    ObjectDataSource 控件

    对于数据源控件直接与数据存储通信的双层应用程序,我们目前已涵盖的数据源控件是绝佳的选择。 但是,许多实际应用程序是多层应用程序,其中数据源控件可能需要与业务对象通信,而业务对象又与数据层通信。 在这些情况下,ObjectDataSource 可以很好地填充帐单。 ObjectDataSource 与源对象结合使用。 如果对象具有实例方法而不是静态方法,则 ObjectDataSource 控件将在单个请求的范围内创建源对象的实例,调用指定的方法并释放对象实例(如果对象具有实例方法,而不是静态方法 (Visual Basic 中共享) )。 因此,对象必须是无状态的。 也就是说,对象应获取并释放单个请求范围内的所有必需资源。 可以通过处理 ObjectDataSource 控件的 ObjectCreating 事件来控制源对象的创建方式。 可以创建源对象的实例,然后将 ObjectDataSourceEventArgs 类的 ObjectInstance 属性设置为该实例。 ObjectDataSource 控件将使用在 ObjectCreating 事件中创建的实例,而不是单独创建实例。

    如果 ObjectDataSource 控件的源对象公开了公共静态方法 (Visual Basic 中共享) ,这些方法可以调用以检索和修改数据,则 ObjectDataSource 控件将直接调用这些方法。 如果 ObjectDataSource 控件必须创建源对象的实例才能进行方法调用,则对象必须包含不采用任何参数的公共构造函数。 ObjectDataSource 控件在创建源对象的新实例时将调用此构造函数。

    如果源对象不包含不带参数的公共构造函数,则可以创建将由 ObjectCreating 事件中的 ObjectDataSource 控件使用的源对象的实例。

    指定对象方法

    ObjectDataSource 控件的源对象可以包含用于选择、插入、更新或删除数据的任何数量的方法。 这些方法由 ObjectDataSource 控件根据方法的名称调用,通过使用 ObjectDataSource 控件的 SelectMethod、InsertMethod、UpdateMethod 或 DeleteMethod 属性进行标识。 源对象还可以包含可选的 SelectCount 方法,该方法由 ObjectDataSource 控件使用 SelectCountMethod 属性标识,该方法返回数据源中对象总数的计数。 在调用 Select 方法后,ObjectDataSource 控件将调用 SelectCount 方法,以检索数据源中的记录总数,以便在分页时使用。

    使用数据源控件的实验室

    练习 1 - 使用 SqlDataSource 控件显示数据

    以下练习使用 SqlDataSource 控件连接到 Northwind 数据库。 它假定你有权访问 SQL Server 2000 实例上的 Northwind 数据库。

  • 创建新的 ASP.NET 网站。

  • 添加新web.config文件。

  • 右键单击解决方案资源管理器中的项目,然后单击“添加新项”。
  • 从模板列表中选择“Web 配置文件”,然后单击“添加”。
  • <编辑 connectionStrings> 部分,如下所示:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ConnectionStrings:Northwind%>"
        SelectCommand="SELECT * FROM Products">
    </asp:SqlDataSource>
    
  • 切换到“代码”视图,将 ConnectionString 属性和 SelectCommand 属性添加到 <asp:SqlDataSource> 控件,如下所示:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ConnectionStrings:Northwind%>"
        SelectCommand="SELECT * FROM Products">
    </asp:SqlDataSource>
    
  • 在“设计”视图中,添加新的 GridView 控件。

  • 从“GridView 任务”菜单的“选择数据源”下拉列表中,选择“SqlDataSource1”。

  • 右键单击 Default.aspx,然后从菜单中选择“在浏览器中查看”。 出现保存提示时,单击“是”。

  • GridView 显示 Products 表中的数据。

    练习 2 - 使用 SqlDataSource 控件编辑数据

    以下练习演示如何使用声明性语法对 DropDownList 控件进行数据绑定,并允许编辑 DropDownList 控件中显示的数据。

  • 在“设计”视图中,从 Default.aspx 中删除 GridView 控件。

    重要说明:将 SqlDataSource 控件保留在页面上。

  • 将 DropDownList 控件添加到 Default.aspx。

  • 切换到“源”视图。

  • 将 DataSourceId、DataTextField 和 DataValueField 属性添加到 <asp:DropDownList> 控件,如下所示:

    <asp:DropDownList ID="ddlProducts" runat="server"
         DataSourceId="SqlDataSource1" DataTextField="ProductName"
         DataValueField="ProductID">
    </asp:DropDownList>
    
  • 保存 Default.aspx 并在浏览器中查看它。 请注意,DropDownList 包含 Northwind 数据库中的所有产品。

  • 关闭浏览器。

  • 在 Default.aspx 的“源”视图中,在 DropDownList 控件下方添加新的 TextBox 控件。 将 TextBox 的 ID 属性更改为 txtProductName。

  • 在 TextBox 控件下,添加新的 Button 控件。 将 Button 的 ID 属性更改为 btnUpdate,将 Text 属性更改为 Update Product Name

  • 在 Default.aspx 的“源”视图中,将一个 UpdateCommand 属性和两个新的 UpdateParameters 添加到 SqlDataSource 标记,如下所示:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ConnectionStrings:Northwind%>"
        SelectCommand="SELECT * FROM Products"
        UpdateCommand="UPDATE Products SET ProductName=@ProductName WHERE ProductID=@ProductID">
          <UpdateParameters>
          <asp:ControlParameter Name="ProductName" 
            ControlID="txtProductName" PropertyName="Text" />
          <asp:ControlParameter Name="ProductID" 
            ControlID="ddlProducts" PropertyName="SelectedValue" />
    </asp:SqlDataSource>
    

    请注意,) 此代码中添加了两个更新参数 (ProductName 和 ProductID。 这些参数映射到 txtProductName TextBox 的 Text 属性和 ddlProducts DropDownList 的 SelectedValue 属性。

  • 切换到“设计”视图,然后双击“按钮”控件以添加事件处理程序。

  • 将以下代码添加到btnUpdate_Click代码:

    SqlDataSource1.Update();
    
  • 右键单击“Default.aspx”,然后选择在浏览器中查看它。 出现提示时,单击“是”以保存所有更改。

  • ASP.NET 2.0 分部类允许在运行时进行编译。 无需生成应用程序即可看到代码更改生效。

  • 从 DropDownList 中选择一个产品。

  • 在 TextBox 中输入所选产品的新名称,然后单击“更新”按钮。

  • 产品名称在数据库中更新。

    练习 3 使用 ObjectDataSource 控件

    本练习将演示如何使用 ObjectDataSource 控件和源对象与 Northwind 数据库交互。

  • 右键单击解决方案资源管理器中的项目,然后单击“添加新项”。

  • 在模板列表中选择“Web 窗体”。 将名称更改为 object.aspx,然后单击“添加”。

  • 右键单击解决方案资源管理器中的项目,然后单击“添加新项”。

  • 在模板列表中选择“类”。 将 类的名称更改为 NorthwindData.cs,然后单击“添加”。

  • 当系统提示将类添加到 App_Code 文件夹时,单击“是”。

  • 将以下代码添加到 NorthwindData.cs 文件:

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Data.SqlClient;
    public class NorthwindData {
        private string _connectionString;
        public NorthwindData() {
            Initialize();
        private void Initialize() {
            if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
                ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == "") {
                    throw new Exception("A connection string named 'Northwind' with " +
                    "a valid connection string must exist in the <connectionStrings> " +
                    "configuration section for the application.");
            _connectionString = ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
        public DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords) {
            VerifySortColumns(sortColumns);
            string sqlCmd = "SELECT EmployeeID, LastName, FirstName, Address, " +
                "City, Region, PostalCode FROM Employees ";
            if (sortColumns.Trim() == "")
                sqlCmd += "ORDER BY EmployeeID";
                sqlCmd += "ORDER BY " + sortColumns;
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlDataAdapter da = new SqlDataAdapter(sqlCmd, conn);
            DataSet ds = new DataSet();
            try {
                conn.Open();
                da.Fill(ds, startRecord, maxRecords, "Employees");
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            return ds.Tables["Employees"];
        public int SelectCount() {
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Employees", conn);
            int result = 0;
            try {
                conn.Open();
                result = (int)cmd.ExecuteScalar();
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            return result;
        //////////
        // Verify that only valid columns are specified in the sort expression to
        // avoid a SQL Injection attack.
        private void VerifySortColumns(string sortColumns) {
            if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
                sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);
            string[] columnNames = sortColumns.Split(',');
            foreach (string columnName in columnNames) {
                switch (columnName.Trim().ToLowerInvariant()) {
                    case "employeeid":
                        break;
                    case "lastname":
                        break;
                    case "firstname":
                        break;
                    case "":
                        break;
                    default:
                        throw new ArgumentException("SortColumns contains an " +
                            "invalid column name.");
                        break;
        // Select an employee.
        public DataTable GetEmployee(int EmployeeID) {
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlDataAdapter da =
                new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, " +
                "Address, City, Region, PostalCode " +
                " FROM Employees WHERE EmployeeID = @EmployeeID", conn);
            da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
            DataSet ds = new DataSet();
            try {
                conn.Open();
                da.Fill(ds, "Employees");
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            return ds.Tables["Employees"];
        // Delete the Employee by ID.
        public int DeleteEmployee(int EmployeeID) {
             SqlConnection conn = new SqlConnection(_connectionString);
             SqlCommand cmd = new SqlCommand("DELETE FROM Employees WHERE " +
                 "EmployeeID = @EmployeeID", conn);
             cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
             int result = 0;
             try {
                 conn.Open();
                 result = cmd.ExecuteNonQuery();
             } catch (SqlException e) {
                 // Handle exception.
             } finally {
                 conn.Close();
             return result;
         // Update the Employee by original ID.
         public int UpdateEmployee(int EmployeeID, string LastName, string FirstName,
             string Address, string City, string Region,
             string PostalCode) {
             if (String.IsNullOrEmpty(FirstName))
                 throw new ArgumentException("FirstName cannot be null or an empty string.");
             if (String.IsNullOrEmpty(LastName))
                 throw new ArgumentException("LastName cannot be null or an empty string.");
             if (Address == null) { Address = String.Empty; }
             if (City == null) { City = String.Empty; }
             if (Region == null) { Region = String.Empty; }
             if (PostalCode == null) { PostalCode = String.Empty; }
             SqlConnection conn = new SqlConnection(_connectionString);
             SqlCommand cmd = new SqlCommand("UPDATE Employees " +
                 " SET FirstName=@FirstName, " +
                 "LastName=@LastName, " +
                 "Address=@Address, City=@City, " +
                 "Region=@Region, " +
                 "PostalCode=@PostalCode " +
                 "WHERE EmployeeID=@EmployeeID", conn);
             cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;
             cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
             cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
             cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
             cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
             cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
             cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
             int result = 0;
             try {
                 conn.Open();
                 result = cmd.ExecuteNonQuery();
             } catch (SqlException e) {
                 // Handle exception.
             } finally {
                 conn.Close();
             return result;
        // Insert an Employee.
        public int InsertEmployee(string LastName, string FirstName,
            string Address, string City, string Region,
            string PostalCode) {
            if (String.IsNullOrEmpty(FirstName))
                throw new ArgumentException("FirstName cannot be null or an empty string.");
            if (String.IsNullOrEmpty(LastName))
                throw new ArgumentException("LastName cannot be null or an empty string.");
            if (Address == null) { Address = String.Empty; }
            if (City == null) { City = String.Empty; }
            if (Region == null) { Region = String.Empty; }
            if (PostalCode == null) { PostalCode = String.Empty; }
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand("INSERT INTO Employees " +
                " (FirstName, LastName, Address, " +
                " City, Region, PostalCode) " +
                " Values(@FirstName, @LastName, " +
                "@Address, @City, @Region, @PostalCode); " +
                "SELECT @EmployeeID = SCOPE_IDENTITY()", conn);
            cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;
            cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
            cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
            cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
            cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
            cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
            SqlParameter p = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int);
                p.Direction = ParameterDirection.Output;
            int newEmployeeID = 0;
            try {
                conn.Open();
                cmd.ExecuteNonQuery();
                newEmployeeID = (int)p.Value;
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            return newEmployeeID;
        // Methods that support Optimistic Concurrency checks.
        // Delete the Employee by ID.
        public int DeleteEmployee(int original_EmployeeID, string original_LastName,
            string original_FirstName, string original_Address,
            string original_City, string original_Region,
            string original_PostalCode) {
            if (String.IsNullOrEmpty(original_FirstName))
                throw new ArgumentException("FirstName cannot be null or an empty string.");
            if (String.IsNullOrEmpty(original_LastName))
                throw new ArgumentException("LastName cannot be null or an empty string.");
            if (original_Address == null) { original_Address = String.Empty; }
            if (original_City == null) { original_City = String.Empty; }
            if (original_Region == null) { original_Region = String.Empty; }
            if (original_PostalCode == null) { original_PostalCode = String.Empty; }
            string sqlCmd = "DELETE FROM Employees WHERE EmployeeID = " + @original_EmployeeID
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand(sqlCmd, conn);
            cmd.Parameters.Add("@original_EmployeeID",
                SqlDbType.Int).Value = original_EmployeeID;
            cmd.Parameters.Add("@original_FirstName",
                SqlDbType.VarChar, 10).Value = original_FirstName;
            cmd.Parameters.Add("@original_LastName",
                SqlDbType.VarChar, 20).Value = original_LastName;
            cmd.Parameters.Add("@original_Address",
                SqlDbType.VarChar, 60).Value = original_Address;
            cmd.Parameters.Add("@original_City",
                SqlDbType.VarChar, 15).Value = original_City;
            cmd.Parameters.Add("@original_Region",
                SqlDbType.VarChar, 15).Value = original_Region;
            cmd.Parameters.Add("@original_PostalCode",
                SqlDbType.VarChar, 10).Value = original_PostalCode;
            int result = 0;
            try {
                conn.Open();
                result = cmd.ExecuteNonQuery();
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            return result;
        // Update the Employee by original ID.
        public int UpdateEmployee(string LastName, string FirstName,
            string Address, string City, string Region,
            string PostalCode, int original_EmployeeID,
            string original_LastName, string original_FirstName,
            string original_Address, string original_City,
            string original_Region, string original_PostalCode) {
            if (String.IsNullOrEmpty(FirstName))
                throw new ArgumentException("FirstName cannot be null or an empty string.");
            if (String.IsNullOrEmpty(LastName))
                throw new ArgumentException("LastName cannot be null or an empty string.");
            if (Address == null) { Address = String.Empty; }
            if (City == null) { City = String.Empty; }
            if (Region == null) { Region = String.Empty; }
            if (PostalCode == null) { PostalCode = String.Empty; }
            if (original_Address == null) { original_Address = String.Empty; }
            if (original_City == null) { original_City = String.Empty; }
            if (original_Region == null) { original_Region = String.Empty; }
            if (original_PostalCode == null) { original_PostalCode = String.Empty; }
            string sqlCmd = "UPDATE Employees " +
                " SET FirstName = @FirstName, LastName = @LastName, " +
                " Address = @Address, City = @City, Region = @Region, " +
                " PostalCode = @PostalCode " +
                " WHERE EmployeeID = @original_EmployeeID";
            SqlConnection conn = new SqlConnection(_connectionString);
            SqlCommand cmd = new SqlCommand(sqlCmd, conn);
            cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;
            cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
            cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
            cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
            cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
            cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
            cmd.Parameters.Add("@original_EmployeeID",
                SqlDbType.Int).Value = original_EmployeeID;
            cmd.Parameters.Add("@original_FirstName",
                SqlDbType.VarChar, 10).Value = original_FirstName;
            cmd.Parameters.Add("@original_LastName",
                SqlDbType.VarChar, 20).Value = original_LastName;
            cmd.Parameters.Add("@original_Address",
                SqlDbType.VarChar, 60).Value = original_Address;
            cmd.Parameters.Add("@original_City",
                SqlDbType.VarChar, 15).Value = original_City;
            cmd.Parameters.Add("@original_Region",
                SqlDbType.VarChar, 15).Value = original_Region;
            cmd.Parameters.Add("@original_PostalCode",
                SqlDbType.VarChar, 10).Value = original_PostalCode;
            int result = 0;
            try {
                conn.Open();
                result = cmd.ExecuteNonQuery();
            } catch (SqlException e) {
                // Handle exception.
            } finally {
                conn.Close();
            return result;
    
  • 将以下代码添加到 object.aspx 的“源”视图:

    <%@ Page language="C#" %>
    <script RunAt="server">
    void EmployeesDetailsView_ItemInserted(Object sender, DetailsViewInsertedEventArgs e) {
        EmployeesGridView.DataBind();
    void EmployeesDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e) {
        EmployeesGridView.DataBind();
    void EmployeesDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e) {
        EmployeesGridView.DataBind();
    void EmployeesGridView_OnSelectedIndexChanged(object sender, EventArgs e) {
        EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
            EmployeesGridView.SelectedDataKey.Value.ToString();
        EmployeesDetailsView.DataBind();
    void EmployeeDetailsObjectDataSource_OnInserted(object sender,
        ObjectDataSourceStatusEventArgs e) {
        EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
            e.ReturnValue.ToString();
        EmployeesDetailsView.DataBind();
    void EmployeeDetailsObjectDataSource_OnUpdated(object sender,
        ObjectDataSourceStatusEventArgs e) {
        if ((int)e.ReturnValue == 0)
            Msg.Text = "Employee was not updated. Please try again.";
    void EmployeeDetailsObjectDataSource_OnDeleted(object sender,
        ObjectDataSourceStatusEventArgs e) {
        if ((int)e.ReturnValue == 0)
            Msg.Text = "Employee was not deleted. Please try again.";
    void Page_Load() {
        Msg.Text = "";
    </script>
        <form id="Form1" runat="server">
          <h3>ObjectDataSource Example</h3>
          <asp:Label id="Msg" runat="server" ForeColor="Red" />
          <asp:ObjectDataSource
              ID="EmployeesObjectDataSource"
              runat="server"
              TypeName="NorthwindData"
              SortParameterName="SortColumns"
              EnablePaging="true"
              SelectCountMethod="SelectCount"
              StartRowIndexParameterName="StartRecord"
              MaximumRowsParameterName="MaxRecords"
              SelectMethod="GetAllEmployees" >
          </asp:ObjectDataSource>
          <asp:ObjectDataSource
              ID="EmployeeDetailsObjectDataSource"
              runat="server"
              TypeName="NorthwindData"
              ConflictDetection="CompareAllValues"
              OldValuesParameterFormatString="{0}"
              SelectMethod="GetEmployee"
              InsertMethod="InsertEmployee"
              UpdateMethod="UpdateEmployee"
              DeleteMethod="DeleteEmployee"
              OnInserted="EmployeeDetailsObjectDataSource_OnInserted"
              OnUpdated="EmployeeDetailsObjectDataSource_OnUpdated"
              OnDeleted="EmployeeDetailsObjectDataSource_OnDeleted">
              <SelectParameters>
                  <asp:Parameter Name="EmployeeID" Type="Int32" />
              </SelectParameters>
          </asp:ObjectDataSource>
          <table cellspacing="10">
              <td valign="top">
                <asp:GridView ID="EmployeesGridView"
                    DataSourceID="EmployeesObjectDataSource"
                    AutoGenerateColumns="false"
                    AllowSorting="true"
                    AllowPaging="true"
                    PageSize="5"
                    DataKeyNames="EmployeeID"
                    OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
                    RunAt="server">
                    <HeaderStyle backcolor="lightblue" forecolor="black"/>
                    <Columns>
                    <asp:ButtonField Text="Details..."
                    HeaderText="Show Details"
                    CommandName="Select"/>
                    <asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"
                    SortExpression="EmployeeID" />
                    <asp:BoundField DataField="FirstName" HeaderText="First Name"
                    SortExpression="FirstName" />
                    <asp:BoundField DataField="LastName" HeaderText="Last Name"
                    SortExpression="LastName, FirstName" />
                    </Columns>
                </asp:GridView>
              <td valign="top">
                <asp:DetailsView ID="EmployeesDetailsView"
                    DataSourceID="EmployeeDetailsObjectDataSource"
                    AutoGenerateRows="false"
                    EmptyDataText="No records."
                    DataKeyNames="EmployeeID"
                    Gridlines="Both"
                    AutoGenerateInsertButton="true"
                    AutoGenerateEditButton="true"
                    AutoGenerateDeleteButton="true"
                    OnItemInserted="EmployeesDetailsView_ItemInserted"
                    OnItemUpdated="EmployeesDetailsView_ItemUpdated"
                    OnItemDeleted="EmployeesDetailsView_ItemDeleted"
                    RunAt="server">
                    <HeaderStyle backcolor="Navy" forecolor="White"/>
                    <RowStyle backcolor="White"/>
                    <AlternatingRowStyle backcolor="LightGray"/>
                    <EditRowStyle backcolor="LightCyan"/>
                    <Fields>
                        <asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"
                            InsertVisible="False" ReadOnly="true"/>
                        <asp:BoundField DataField="FirstName" HeaderText="First Name"/>
                        <asp:BoundField DataField="LastName" HeaderText="Last Name"/>
                        <asp:BoundField DataField="Address" HeaderText="Address"/>
                        <asp:BoundField DataField="City" HeaderText="City"/>
                        <asp:BoundField DataField="Region" HeaderText="Region"/>
                        <asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>
                    </Fields>
                  </asp:DetailsView>
            </table>
          </form>
        </body>
      </html>
    
  • 保存所有文件并浏览 object.aspx。

  • 通过查看详细信息、编辑员工、添加员工和删除员工来与界面进行交互。

    Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback.

    提交和查看相关反馈

  •