音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

在ASP.NET 2.0中操作数据之三十七:DataList批量更新
日期:2021-09-07 22:13:53   来源:脚本之家

导言

  在前面我们学习了如何创建item级的DataList。和可编辑的GridView一样,每个DataList里的item都包含一个Edit button,当点击时,item会变的可编辑。item级的编辑在偶尔需要更新时没什么问题,但是在有些情况下用户需要编辑大量的记录。如果一个用户需要编辑许多记录,他会被迫去不停的去点击Edit,作出修改,然后点击Update,这些大量的点击会妨碍他的工作效率。在这样的情况下,一个好的选择是提供一个完全可编辑的DataList,它的所有的item都处于编辑模式下,它的所有的值都可以通过点击一个“Update All”button来更新。见图1。

//img.jbzj.com/file_images/article/201605/2016051210152817.png
图 1: 一个完全可编辑的DataList 的所有item都可以被修改

  本章我们来学习如何创建一个完全可编辑的DataList,它提供用户更新supplier的address的功能。

第一步: 在DataList的 ItemTemplate创建一个可编辑的用户界面

在前面创建一个标准的item级编辑的DataList时,我们使用了两个template:

ItemTemplate — 包含只读的用户界面(使用 Label 显示每个product的 name 和price).
EditItemTemplate — 包含编辑的用户界面(两个TextBox ).

  DataList的EditItemIndex属性表明了哪个DataListItem使用EditItemTemplate来展示(如果有的话)。即ItemIndex的值等于DataList的EditItemIndex的DataListItem使用EditItemTemplate来展示。在一次只编辑一个item的情况下,这个模式工作的很好,但是在创建完全可编辑的DataList的时候就不适用了。

  对完全可编辑的DataList来说,我们需要所有的DataListItem都以可编辑的界面来展示。最简单的方法是在ItemTemplate里定义可编辑的界面。对修改supplier的address信息而言,可编辑界面里supplier表现为文本,address,city和country的值都用TextBox来表示。

  首先打开BatchUpdate.aspx页,添加一个DataList,将ID设为Suppliers。通过智能标签添加一个名为SuppliersDataSource的ObjectDataSource控件。

//img.jbzj.com/file_images/article/201605/2016051210152818.png
图2: 创建一个名为SuppliersDataSource的ObjectDataSource

使用SuppliersBLL类的GetSuppliers()方法配置ObjectDataSource(见图3)。象前面一章那样,我们将直接使用 BLL而不是通过ObjectDataSource来更新supplier信息。在UPDATE标签里选择None(见图4)。

//img.jbzj.com/file_images/article/201605/2016051210152919.png
图 3: 使用GetSuppliers() 方法配置ObjectDataSource

//img.jbzj.com/file_images/article/201605/2016051210152920.png
图 4: 设置UPDATE 标签为None

  完成向导后,Visual Studio会自动生成DataList的ItemTemplate来在Label里显示每个数据字段。我们需要修改这个template让它提供编辑界面。ItemTemplate可以在设计器里通过DataList的智能标签上的Edit Templates或直接写声明语法来自定义。

  创建一个编辑界面,将supplier的name表现为文本,address,city和country表现为TextBox。完成这些后,你的声明代码应该和下面差不多:

<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID"
 DataSourceID="SuppliersDataSource">
 <ItemTemplate>
  <h4><asp:Label ID="CompanyNameLabel" runat="server"
   Text='<%# Eval("CompanyName") %>' /></h4>
  <table border="0">
   <tr>
    <td class="SupplierPropertyLabel">Address:</td>
    <td class="SupplierPropertyValue">
     <asp:TextBox ID="Address" runat="server"
      Text='<%# Eval("Address") %>' />
    </td>
   </tr>
   <tr>
    <td class="SupplierPropertyLabel">City:</td>
    <td class="SupplierPropertyValue">
     <asp:TextBox ID="City" runat="server"
      Text='<%# Eval("City") %>' />
    </td>
   </tr>
   <tr>
    <td class="SupplierPropertyLabel">Country:</td>
    <td class="SupplierPropertyValue">
     <asp:TextBox ID="Country" runat="server"
      Text='<%# Eval("Country") %>' />
    </td>
   </tr>
  </table>
  <br />
 </ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
 OldValuesParameterFormatString="original_{0}"
 SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>

  注意:和前面一章一样,需要为DataList开启view state。

  在ItemTemplate里我使用了两个新的CSS类,SupplierPropertyLabel和SupplierPropertyValue。它们的风格设置和ProductsPropertyLabel和ProductPropertyValue CSS类一样,并已经加入到Styles.css中。

.ProductPropertyLabel, .SupplierPropertyLabel
{
 font-weight: bold;
 text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
 padding-right: 35px;
}

完成这些后浏览页面。如图5所示,每个DataList的item用文本显示supplier name,用TextBox显示address,city和country。

//img.jbzj.com/file_images/article/201605/2016051210152921.png
图 5:  DataList里的每个Supplier都可编辑

第二步: 增加“Update All” Button

  图5里显示的信息暂时还没提供Update按钮。完全可编辑的DataList应该只包含一个"Update All"按钮,而不是象前面那样,每个item包含一个button。当点击"Update All"时,DataList里的所有记录将被更新。本章我们将添加两个"Update All"button- 一个在页的上面,一个在下面(两个都提供相同的功能)。

  先在DataList上面添加一个ID为UpdateAll1的Button。然后在DataList下面添加ID为UpdataAll2的Button。两个Button的Text都设为"Update All"。最后为两个Button的Click事件都创建一个event handler。我们创建一个方法,“UpdateAllSupplierAddress”,然后在事件处理中调用它。(而不是在两个事件处理里复制相同的代码)

protected void UpdateAll1_Click(object sender, EventArgs e)
{
 UpdateAllSupplierAddresses();
}
protected void UpdateAll2_Click(object sender, EventArgs e)
{
 UpdateAllSupplierAddresses();
}
private void UpdateAllSupplierAddresses()
{
 // TODO: Write code to update _all_ of the supplier addresses in the DataList
}

图6是添加完"Update All"button后的页面。

//img.jbzj.com/file_images/article/201605/2016051210152922.png
图 6: 页面添加了两个“Update All” Button

第三步: 更新所有的Suppliers的 Address 信息

  完成了将所有的item显示为可编辑的界面和添加了“Update All”button后,剩下的事就是写代码执行批量更新。我们需要便利DataList的item,调用SuppliersBLL类的UpdateSupplierAddress方法。

  可以通过DataList的Items property 来访问DataListItem集合。通过DataListItem的引用,我们可以从DataKeys集合里获取相关的SuppliserID,并引用ItemTemplate里的TextBox,见下面的代码:

private void UpdateAllSupplierAddresses()
{
 // Create an instance of the SuppliersBLL class
 SuppliersBLL suppliersAPI = new SuppliersBLL();
 // Iterate through the DataList's items
 foreach (DataListItem item in Suppliers.Items)
 {
  // Get the supplierID from the DataKeys collection
  int supplierID = Convert.ToInt32(Suppliers.DataKeys[item.ItemIndex]);
  // Read in the user-entered values
  TextBox address = (TextBox)item.FindControl("Address");
  TextBox city = (TextBox)item.FindControl("City");
  TextBox country = (TextBox)item.FindControl("Country");
  string addressValue = null, cityValue = null, countryValue = null;
  if (address.Text.Trim().Length > 0)
   addressValue = address.Text.Trim();
  if (city.Text.Trim().Length > 0)
    cityValue = city.Text.Trim();
  if (country.Text.Trim().Length > 0)
   countryValue = country.Text.Trim();
  // Call the SuppliersBLL class's UpdateSupplierAddress method
  suppliersAPI.UpdateSupplierAddress
   (supplierID, addressValue, cityValue, countryValue);
 }
}

  当用户点击一个"Update All"button时,每个Supplier DataList里的DataListItem都执行UpdateAllSupplierAddress方法,并调用SuppliersBLL类的UpdateSupplierAddress方法,将相关的值传过去。如果address,city或country里不输入值,UpdateSupplierAddress会接收一个空值(不是空字符串),而相关的字段的结果会是一个database NULL。

  注意:你可以添加一个显示的状态Label,当批量更新完成后通过它来提供一些确认信息。只更新 Addresses被修改过的记录

  本章使用的批量更新法则为每个DataList里的supplier调用UpdateSupplierAddress方法,无论address信息是否被修改过。虽然这种盲目的更新一般情况下不会有什么性能问题,但是如果你有做数据库表的审计,那样将会导致很多多余的记录。每次用户点击"Update All"button后,不管用户是否有修改,系统里都会为每个supplier产生一个一条新的审计记录。

  ADO.NET的DateTable和DataAdapter类被设计用来支持批量更新那些仅仅被修改,删除或新增的记录。DataTable的每个row都有RowState property 来指明这个row是否是新增到DataTable或从它里面删除,修改,或没有改变。当DataTable刚产生时,所有的row都被标记为未修改的,修改了row的任何列后row会被标记为已修改的。

  在SuppliersBLL类里我们首先将supplier的记录读进SuppliersDataTable里然后设置Address,City和Country列的值来更新指定的supplier的信息,见以下代码:

public bool UpdateSupplierAddress
 (int supplierID, string address, string city, string country)
{
 Northwind.SuppliersDataTable suppliers =
  Adapter.GetSupplierBySupplierID(supplierID);
 if (suppliers.Count == 0)
  // no matching record found, return false
  return false;
 else
 {
  Northwind.SuppliersRow supplier = suppliers[0];
  if (address == null)
   supplier.SetAddressNull();
  else
   supplier.Address = address;
  if (city == null)
   supplier.SetCityNull();
  else
   supplier.City = city;
  if (country == null)
   supplier.SetCountryNull();
  else
   supplier.Country = country;
  // Update the supplier Address-related information
  int rowsAffected = Adapter.Update(supplier);
  // Return true if precisely one row was updated,
  // otherwise false
  return rowsAffected == 1;
 }
}

  无论值是否有被修改,这段代码都将传入的address,city和country的值赋给SuppliersDataTable的SuppliersRow。这个修改将使SuppliersRow的RowState属性被标记为已修改的。当DAL的Update方法被调用时,它发现SupplierRow已经被修改了,因此向数据库发送UPDATE命令。

  然而想象一下,我们为这个方法添加的代码仅仅在和已经存在的值不一样时才将传入的address,city和country的值赋给SuppliersRow。在address,city和country没有修改的情况下,SupplierRow的RowState仍然标记为未改变。这样的结果是当DAL的Update方法被调用时,SuppliersRow没有被修改,因此不会调用数据库。使用以下的代码代替前面盲目的赋值:

// Only assign the values to the SupplierRow's column values if they differ
if (address == null && !supplier.IsAddressNull())
 supplier.SetAddressNull();
else if ((address != null && supplier.IsAddressNull()) ||
   (!supplier.IsAddressNull() &&
   string.Compare(supplier.Address, address) != 0))
 supplier.Address = address;
if (city == null && !supplier.IsCityNull())
 supplier.SetCityNull();
else if ((city != null && supplier.IsCityNull()) ||
   (!supplier.IsCityNull() && string.Compare(supplier.City, city) != 0))
 supplier.City = city;
if (country == null && !supplier.IsCountryNull())
 supplier.SetCountryNull();
else if ((country != null && supplier.IsCountryNull()) ||
   (!supplier.IsCountryNull() &&
   string.Compare(supplier.Country, country) != 0))
 supplier.Country = country; 

增加了这些代码后,DAL的Update方法仅仅在更改过address相关的值的那些记录里才向数据库发送UPDATE命令。

  当然我们也可以追踪传入的字段和数据库数据是否有区别,如果没有,就不需要调用DAL的Update方法。这种方法在你使用直接的数据库命令时非常有效,因为直接的数据库命令不会检查SuppliersRow来决定是否需要调用数据库。

  注意:每次UpdateSupplierAddress方法被调用时,都会调用一次数据库来获取需要更新的记录的信息。如果数据被修改,又要调用一次数据库来更新数据。这个流程可以通过创建一个重载的UpdateSupplierAddress方法来优化,这个方法接受一个EmployeesDataTable ,它包含BatchUpdate.aspx页的所有的修改。然后它会调用一次数据库来获取Suppliers表里的所有记录。在结果集里仅仅是被修改过的记录才能被更新。

总结

  本章学习了如何创建一个完全可编辑的DataList。通过它用户可以快速的修改多个supplier的address信息。我们首先定义了编辑界面 — address,city和country都以TextBox来表示 — 在DataList的ItemTemplate里。然后我们在DataList的上下各添加了一个“Update All”button。用户修改完后,点击其中一个后,每个DataListItem都会调用SuppliersBLL类的UpdateSupplierAddress方法。

  祝编程愉快!

作者简介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用 微软Web技术。大家可以点击查看全部教程《[翻译]Scott Mitchell 的ASP.NET 2.0数据教程》,希望对大家的学习ASP.NET有所帮助。

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    ASP编程JSP编程PHP编程.NET编程python编程