婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 在ASP.NET 2.0中操作數據之六十一:在事務里對數據庫修改進行封裝

在ASP.NET 2.0中操作數據之六十一:在事務里對數據庫修改進行封裝

熱門標簽:蘇州如何辦理400電話 臨沂智能電話機器人加盟 西寧呼叫中心外呼系統線路商 聯通官網400電話辦理 網絡電話外呼系統上海 外呼電話機器人成本 400電話辦理怎么樣 百應電話機器人外呼系統 地圖標注軟件免費下載

導言:

  正如我們在第16章《概述插入、更新和刪除數據》里探討的那樣,GridView控件內建的功能支持對每行數據的編輯和刪除功能,你只需要稍稍動一下鼠標就可以創建豐富的數據修改界面而不用寫一行代碼.但是,在某些情況下,這還不夠,我們需要讓用戶能夠成批地處理數據.

  比如,很多基于web(web-based)的電子郵件客戶端,將所有郵件出來,每條郵件除了包含郵件信息(主題、發送者等)外,還包含一個checkbox控件。這些界面允許用戶同時刪除多個郵件,用戶只需要選中郵件,再點"刪除所選郵件"按鈕.當用戶要編輯多條不同的記錄的時候,提供一個批編輯界面是比較理想的.我們用不著讓用戶每次都選中一條要編輯的記錄,再做相關的修改,最后點“更新”按鈕,在批編輯界面里每條記錄都有各自的編輯選項,用戶可以快速地編輯多條記錄再點“Update All”按鈕來保存對他們所做的修改.本系列我們將考察如何創建對數據進行添加、編輯、刪除批處理的界面.

  如果想對批處理執行atomic operation(原子操作), 那么首先,所做的操作要么都執行成功要么都失敗,另外還要對數據訪問層進行擴充以支持database transactions(數據庫事務)。數據庫事務確保INSERT, UPDATE, 和 DELETE語句執行的atomicity(原子數)置于數據庫事務的保護之下.另外,絕大多數的當代數據庫系統都支持數據庫事務.

  在本系列我們先看如何擴充數據訪問層以支持數據庫事務,接下來我們看如何創建頁面以包含添加、更新、刪除數據的批處理界面,讓我們開始吧.

  注意:在批處理事務里修改數據時,原子數(atomicity)并非總數必要的。在批處理的某些情況下,某些修改成功某些修改失敗是可以接受的。比如刪除電子郵件時,有些郵件在刪除過程中發生了數據庫錯誤,有些郵件沒有發生錯誤,對這種沒有發生錯誤的郵件,批處理照樣將其刪除掉.對這種情況,我們沒有必要設置數據訪問層DAL支持數據庫事務.不過在其它某些情況下,原子數是至關重要的.比如某個客戶想把資金從一個銀行帳戶轉移到另一個銀行帳號,下面2個操作必須執行成功:首先,將第一個帳號的資金扣除,然后將資金轉入第二個帳號.如果第一步執行成功,第二步執行失敗,銀行當然高興,客戶怕是要發瘋了.在后面的文章里我們將創建添加、更新、刪除的批處理界面,就算你不打算在這些頁面里使用數據庫事務,我也希望你照著本篇文章,對數據訪問層進行擴展一支持數據庫事務.

事務概述

絕大多數的數據庫都支持事務,它可以將多個數據庫命令當成一個邏輯單位進行處理.這些包含事務的命令要么都執行成功要么都執行失敗.

一般來說,事務通過SQL命令來執行,使用如下的模式:

1.聲明事務開始
2.執行構成事務的那些SQL命令
3.如果在第二步中的任何一個命令出錯,執行事務回滾(rollback the transaction)
4.如果在第二步中的所有命令成功執行,提交事務

  這些SQL命令可以通過手寫的方式輸入,比如寫SQL腳本、創建存儲過程、也可以通過編程的方式來構建,比如使用ADO.NET技術或調用System.Transactions namespace命名空間的類.在本文,我們僅僅考察用ADO.NET技術管理事務.在后面的教程我們看如何在數據訪問層Data Access Layer里使用存儲過程,到那時,我們再來考察這些創建、回滾、提交事物的SQL命令。另外,要獲得更多信息請參考文章《Managing Transactions in SQL Server Stored Procedures》(http://www.4guysfromrolla.com/webtech/080305-1.shtml)

  注意:System.Transactions namespace命名空間的TransactionScope class類允許開發者通過編程的方式獲取事務里的一系列命令,且允許事務包含多個數據源,甚至類型不同,比如:Microsoft SQL Server database, 或Oracle database,甚至Web service.本教程我們使用ADO.NET技術而非TransactionScope class類,是因為ADO.NET指定數據庫事務更詳細,且在很多情況下占用資源更少.此外,在某些情況下,TransactionScope class類要用到Microsoft Distributed Transaction Coordinator (MSDTC),圍繞MSDTC的配置、執行和性能問題是比較專業、高級的問題稍微超出了本教程的范圍.

  在ADO.NET里,通過調用SqlConnection class類的BeginTransaction method方法啟動事務, 該方法返回一個SqlTransaction object對象.將構成事務的數據操作命令放在try...catch區域,如果在try區域的某個命令出錯的話,程序將轉到catch區域,在此,通過SqlTransaction object對象的Rollback method方法執行事務回滾。如果所有的命令執行成功,將調用位于try區域底部的SqlTransaction object對象的Commit method方法來提交事務.下面的代碼片段揭示了該模式。要想看在ADO.NET里使用事務的更多例子,請參閱文章《Maintaining Database Consistency with Transactions》(http://aspnet.4guysfromrolla.com/articles/072705-1.aspx).

// Create the SqlTransaction object
SqlTransaction myTransaction = SqlConnectionObject.BeginTransaction();

try
{
 /*
 * ... Perform the database transaction's data modification statements...
 */

 // If we reach here, no errors, so commit the transaction
 myTransaction.Commit();
}
catch
{
 // If we reach here, there was an error, so rollback the transaction
 myTransaction.Rollback();

 throw;
}

  默認情況下,強類型數據集(Typed DataSet)里的TableAdapters并不使用事務。為此,我們要對TableAdapter classes類進行擴展,以包含額外的方法以使用上述模式來執行事務。在第二步,我們看如何使用一個partial classes類來添加這些方法.

第一步:創建批處理數據的頁面

  在我們考察如何擴展數據訪問層DAL以支持數據庫事務之前,讓我們花點時間來創建一些ASP.NET web頁面,我們在本章及后面三章將用到它們.

添加一個名為BatchData的新文件夾,再添加如下的 ASP.NET頁面, 務必套用Site.master模板頁.

Default.aspx
Transactions.aspx
BatchUpdate.aspx
BatchDelete.aspx
BatchInsert.aspx


圖1:添加相關的頁面

就像其它文件夾里的Default.aspx頁面一樣,用SectionLevelTutorialListing.ascx用戶控件來列出本部分的章節。將其從解決資源管理器里拖到Default.aspx頁面.


圖2:將SectionLevelTutorialListing.ascx用戶控件添加到Default.aspx頁面

最后添加如下代碼到Web.sitemap文件,具體的,將其添加到“Customizing the Site Map” siteMapNode>后面:

siteMapNode title="Working with Batched Data"
 url="~/BatchData/Default.aspx"
 description="Learn how to perform batch operations as opposed to
  per-row operations.">
 
 siteMapNode title="Adding Support for Transactions"
 url="~/BatchData/Transactions.aspx"
 description="See how to extend the Data Access Layer to support
  database transactions." />
 siteMapNode title="Batch Updating"
 url="~/BatchData/BatchUpdate.aspx"
 description="Build a batch updating interface, where each row in a
  GridView is editable." />
 siteMapNode title="Batch Deleting"
 url="~/BatchData/BatchDelete.aspx"
 description="Explore how to create an interface for batch deleting
  by adding a CheckBox to each GridView row." />
 siteMapNode title="Batch Inserting"
 url="~/BatchData/BatchInsert.aspx"
 description="Examine the steps needed to create a batch inserting
  interface, where multiple records can be created at the
  click of a button." />
/siteMapNode>

完成后,花幾分鐘在瀏覽器里登錄頁面,左面的菜單列出了本部分的各項


圖3:Site Map現在包含了本章節

第二步:更新數據訪問層以支持數據庫事務

  就像我們在第一章《創建一個數據訪問層》探討的一樣,位于數據訪問層的強類型數據集(Typed DataSet)由DataTables 和 TableAdapters構成.  DataTables保存數據,而TableAdapters提供相應的方法從數據庫讀取數據,并根據DataTables的改動對數據庫做相應的更新,等等.記得TableAdapters有2種更新數據的模式——Batch Update 和 DB-Direct.就Batch Update模式而言, TableAdapter可以傳入DataSet, DataTable, 或DataRows集,遍歷這些數據對要添加、修改、刪除的行執行相應的InsertCommand, UpdateCommand, or DeleteCommand方法。就DB-Direct模式而言,TableAdapter傳入的是那些需要進行添加、更新、刪除操作的某條記錄的列的值,再使用這些值執行相關的InsertCommand, UpdateCommand, 或DeleteCommand命令.

  TableAdapter自動生成的方法并不使用事務.默認狀態下,TableAdapter執行的每一個insert, update, 或delete操作都看作是單獨的、互不相干的.假定在業務邏輯層BLL里使用DB-Direct模式來向數據庫添加十條記錄,代碼將分十次調用TableAdapter的Insert方法. 如果前5條記錄添加正常,而在添加第六條記錄時發生異常,前5條記錄仍然保存在數據庫.同樣的,用Batch Update模式來操作的話,效果亦然.

  在某些情況下,我們想確保在進行一系列的改動時引入原子數(atomicity).為此,我們必須手動擴展TableAdapter,通過添加一些新的方法將InsertCommand, UpdateCommand, 和DeleteCommands命令置于事務之下.在第一章《創建一個數據訪問層》里,我們考察了使用部分類(partial classes)對強類型數據集(Typed DataSet)里的DataTable的函數進行擴充.該技術同樣適用于TableAdapter.

  強類型數據集Northwind.xsd位于App_Code文件夾的DAL子文件夾里.在DAL文件夾里再創建一個名為TransactionSupport的子文件夾,再在里面添加一個新類,名為ProductsTableAdapter.TransactionSupport.cs (見圖4).該類包含ProductsTableAdapter的使用事務的方法.


圖4:創建一個名為TransactionSupport的新文件夾并添加一個名為ProductsTableAdapter.TransactionSupport.cs的新類

在ProductsTableAdapter.TransactionSupport.cs文件里鍵入如下的代碼:

using System;
using System.Data;
using System.Data.SqlClient;
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;

namespace NorthwindTableAdapters
{
 public partial class ProductsTableAdapter
 {
 private SqlTransaction _transaction;
 private SqlTransaction Transaction
 {
 get
 { 
 return this._transaction;
 }
 set
 {
 this._transaction = value;
 }
 }


 public void BeginTransaction()
 {
 // Open the connection, if needed
 if (this.Connection.State != ConnectionState.Open)
 this.Connection.Open();

 // Create the transaction and assign it to the Transaction property
 this.Transaction = this.Connection.BeginTransaction();

 // Attach the transaction to the Adapters
 foreach (SqlCommand command in this.CommandCollection)
 {
 command.Transaction = this.Transaction;
 }

 this.Adapter.InsertCommand.Transaction = this.Transaction;
 this.Adapter.UpdateCommand.Transaction = this.Transaction;
 this.Adapter.DeleteCommand.Transaction = this.Transaction;
 }


 public void CommitTransaction()
 {
 // Commit the transaction
 this.Transaction.Commit();

 // Close the connection
 this.Connection.Close();
 }


 public void RollbackTransaction()
 {
 // Rollback the transaction
 this.Transaction.Rollback();

 // Close the connection
 this.Connection.Close();
 }
 }
}

  類聲明里的關鍵字partial向編譯器表明代碼里添加的成員(members)是添加到命名空間NorthwindTableAdapters里的ProductsTableAdapter class類.我們注意到在文件的頂部有一個using System.Data.SqlClient聲明,這是因為TableAdapter被設置為使用SqlClient provider,在其內部使用一個SqlDataAdapter object對象來向數據庫發出命令.因此,我們需要使用SqlTransaction class類來啟動事務,然后提交或回滾事務.如果沒有使用Microsoft SQL Server數據庫的話,你需要調用恰當的provider.

  這些方法被標記為public,我們可以在ProductsTableAdapter里,或數據訪問層DAL的其它類,甚至是其它層比如業務邏輯層BLL來調用這些法.
BeginTransaction()方法打開了TableAdapter的內部的SqlConnection(如果需要的話), 開啟事務并賦值給Transaction屬性,并將事務分配(attache)給SqlDataAdapter的SqlCommand objects對象.CommitTransaction()和 RollbackTransaction()方法在關閉內部的Connection object對象前分別調用Transaction object對象的Commit 和 Rollback方法.

  添加上述代碼后,我們將在ProductsDataTable 或業務邏輯層BLL里添加方法以執行一系列的置于事務之下的命令. 下面的代碼在Batch Update pattern模式里使用一個事務來更新一個ProductsDataTable instance實例.它調用BeginTransaction method方法來啟動一個事務,然后用一個try...catch模塊來發布數據更改命令.如果調用Adapter object對象的Update方法出現異常,那么將轉到catch區域,對事務進行回滾.記得執行Batch Update pattern模式的Update方法將遍歷ProductsDataTable里的所有行(rows),執行相應的InsertCommand, UpdateCommand, 和DeleteCommands命令.如果這些命令中的其中一個出現異常,事務將回滾,撤銷在事務里的所做的更改.如果Update命令全部執行無異常,那么提交事務.

public int UpdateWithTransaction(Northwind.ProductsDataTable dataTable)
{
 this.BeginTransaction();

 try
 {
 // Perform the update on the DataTable
 int returnValue = this.Adapter.Update(dataTable);

 // If we reach here, no errors, so commit the transaction
 this.CommitTransaction();

 return returnValue;
 }
 catch
 {
 // If we reach here, there was an error, so rollback the transaction
 this.RollbackTransaction();

 throw;
 }
}

  將上述的UpdateWithTransaction()方法添加到文件ProductsTableAdapter.TransactionSupport.cs里的ProductsTableAdapter class類。另外,還可以將該方法添加到業務邏輯層的ProductsBLL class類,不過要做些許修改:即將this.BeginTransaction(), this.CommitTransaction(), and this.RollbackTransaction()三中方法里的關鍵字“this”替換為“Adapter”(我們知道,ProductsBLL類里的ProductsTableAdapter的name屬性即是Adapter).

  UpdateWithTransaction()方法使用的是Batch Update模式,不過也可在事務里調用DB-Direct模式,就像下面的代碼顯示的那樣.DeleteProductsWithTransaction()方法接受一個int類型的ListT>,也就是要刪除的ProductIDs.該方法通過調用BeginTransaction來啟動事務,然后在try模塊里對每一個ProductID值調用DB-Direct模式的Delete方法.如果任何一個對Delete的調用出錯,將轉到catch 模塊,事務將會回滾;如果所有對Delete的調用成功,那就提交事務。添加該方法給ProductsBLL class類.

public void DeleteProductsWithTransaction
 (System.Collections.Generic.Listint> productIDs)
{
 // Start the transaction
 Adapter.BeginTransaction();

 try
 {
 // Delete each product specified in the list
 foreach (int productID in productIDs)
 {
 Adapter.Delete(productID);
 }

 // Commit the transaction
 Adapter.CommitTransaction();
 }
 catch
 {
 // There was an error - rollback the transaction
 Adapter.RollbackTransaction();

 throw;
 }
}

在多個TableAdapters應用事務

  到目前為止我們考察的是對ProductsTableAdapter里的多個命令采用原子操作.如果我們是對多個不同的數據庫表進行改動,并對這些改動執行原子操作那又怎么辦呢?比如:當刪除一個category時,在刪除之前我們想把該種類對應的products分配給其它的category.對這種2步操作——分配products和刪除category——應該執行原子操作.但是ProductsTableAdapter只包含修改Products表的方法;而CategoriesTableAdapter只包含修改Categories表的方法.那么怎樣使用一個包含這2個TableAdapters的事務呢?

  其中一個辦法是向CategoriesTableAdapter添加一個名為DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID)的方法.再定義一個方法來調用一個存儲過程,使用事務來達到分配products和刪除category的目的.我們將在后面考察在一個存儲過程里開始、提交和回滾事務.

  另一個方法是在數據訪問層里添加一個類,來包含DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID)方法.該方法創建CategoriesTableAdapter 和 the ProductsTableAdapter的實例,并將這2個TableAdapters的Connection屬性設置為相同的SqlConnection實例。這樣,它們都將調用BeginTransaction來開啟事務.然后在try...catch模塊里執行分配products和刪除category的方法,最后提交或回滾事務.

第四步:向業務邏輯層添加UpdateWithTransaction方法

  在第三步我們向數據訪問層DAL里的ProductsTableAdapter添加了一個UpdateWithTransaction方法,我們將向業務邏輯層添加相應的方法.雖然表現層可以直接向DAL調用UpdateWithTransaction方法,但是我們在這里仍然將它們分隔開。

  打開ProductsBLL class類,添加一個名為UpdateWithTransaction的方法,該方法僅僅簡單地調用對應的DAL方法.現在ProductsBLL類里有2個方法:UpdateWithTransaction方法——我們才添加的;以及DeleteProductsWithTransaction——我們在第三步添加的.

public int UpdateWithTransaction(Northwind.ProductsDataTable products)
{
 return Adapter.UpdateWithTransaction(products);
}


public void DeleteProductsWithTransaction
 (System.Collections.Generic.Listint> productIDs)
{
 // Start the transaction
 Adapter.BeginTransaction();

 try
 {
 // Delete each product specified in the list
 foreach (int productID in productIDs)
 Adapter.Delete(productID);

 // Commit the transaction
 Adapter.CommitTransaction();
 }
 catch
 {
 // There was an error - rollback the transaction
 Adapter.RollbackTransaction();

 throw;
 }
}

  注意:根ProductsBLL類里的大部分方法不同,上述方法并不包含DataObjectMethodAttribute屬性。這是因為我們將直接在ASP.NET頁面的后臺代碼里調用這些方法,記得DataObjectMethodAttribute方法的作用是指出哪些方法應該出現在ObjectDataSource控件的設置數據源向導的某些標簽(SELECT, UPDATE, INSERT, 或DELETE)里.由于GridView控件缺乏內置的支持“批編輯”或“批刪除”的功能,我們將通過編輯的方式來調用這些方法.

第五步:在表現層更新數據庫數據

  為演示更新一批記錄時事務的作用,我們將創建一個用戶界面來將所有產品用一個GridView控件顯示出來,并包含一個Button Web控件。當點擊該按鈕時為product重新賦值一個有效的CategoryID值。具體來說,對頭幾個products分配一個有效的CategoryID值;而剩下的分配一個無效的(non-existent)CategoryID值,當我們試圖對這樣的一個product——其CategoryID值與現有的category的CategoryID不匹配——進行更新時,將違反外鍵約束,進而拋出一個異常.在本文的示例里你將看到,在使用事務時,當違反外鍵約束拋出一個異常時將導致前面的正確分配CategoryID值的操作產生回滾.如果不使用事務的話,這些正確的操作將執行成功.

  首先,打開BatchData文件夾里的Transactions.aspx頁面,從工具箱拖一個GridView控件到頁面。設置其ID為Products,從其智能標簽里將其綁定到一個名為ProductsDataSource的ObjectDataSource控件,設置該控件調用ProductsBLL class類的GetProducts()方法。由于該GridView是“只讀”的,在UPDATE, INSERT, 和DELETE標簽里選“(None)”,點完成。


圖5:設置ObjectDataSource使用ProductsBLL Class類的GetProducts方法


圖6:在UPDATE, INSERT, 和DELETE標簽里選“(None)”

  完成設置后,Visual Studio將自動的添加BoundFields以及一個CheckBoxField,刪除ProductID, ProductName, CategoryID,和CategoryName以外的其它列;并且分別將ProductName 和 CategoryName列的HeaderText屬性重命名為“Product” 和 “Category”.在智能標簽里啟用“分頁”功能.做完這些修改后,GridView 和 ObjectDataSource控件的聲明代碼看起來應該和下面的差不多:

asp:GridView ID="Products" runat="server" AllowPaging="True"
 AutoGenerateColumns="False" DataKeyNames="ProductID"
 DataSourceID="ProductsDataSource">
 Columns>
 asp:BoundField DataField="ProductID" HeaderText="ProductID"
 InsertVisible="False" ReadOnly="True"
 SortExpression="ProductID" />
 asp:BoundField DataField="ProductName" HeaderText="Product"
 SortExpression="ProductName" />
 asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
 SortExpression="CategoryID" />
 asp:BoundField DataField="CategoryName" HeaderText="Category"
 SortExpression="CategoryName" />
 /Columns>
/asp:GridView>

asp:ObjectDataSource ID="ProductsDataSource" runat="server"
 OldValuesParameterFormatString="original_{0}"
 SelectMethod="GetProducts" TypeName="ProductsBLL">
/asp:ObjectDataSource>

  然后,在GridView控件上添加3個Button Web控件,設置第一個按鈕的Text屬性 為“Refresh Grid”;第二個按鈕的Text屬性為“Modify Categories (WITH TRANSACTION)”;第三個按鈕的Text屬性為“Modify Categories (WITHOUT TRANSACTION)”.

 

p>
 asp:Button ID="RefreshGrid" runat="server" Text="Refresh Grid" />
/p>
p>
 asp:Button ID="ModifyCategoriesWithTransaction" runat="server"
 Text="Modify Categories (WITH TRANSACTION)" />
/p>
p>
 asp:Button ID="ModifyCategoriesWithoutTransaction" runat="server"
 Text="Modify Categories (WITHOUT TRANSACTION)" />
/p>


此時,在Visual Studio的設計模式里,界面看起來和下面的截屏差不多:


圖7:頁面包含一個GridView控件和三個Button Web控件

為這3個按鈕的Click events事件創建事件處理器,如下:

protected void RefreshGrid_Click(object sender, EventArgs e)
{
 Products.DataBind();
}

protected void ModifyCategoriesWithTransaction_Click(object sender, EventArgs e)
{
 // Get the set of products
 ProductsBLL productsAPI = new ProductsBLL();
 Northwind.ProductsDataTable products = productsAPI.GetProducts();

 // Update each product's CategoryID
 foreach (Northwind.ProductsRow product in products)
 {
 product.CategoryID = product.ProductID;
 }

 // Update the data using a transaction
 productsAPI.UpdateWithTransaction(products);

 // Refresh the Grid
 Products.DataBind();
}

protected void ModifyCategoriesWithoutTransaction_Click(object sender, EventArgs e)
{
 // Get the set of products
 ProductsBLL productsAPI = new ProductsBLL();
 Northwind.ProductsDataTable products = productsAPI.GetProducts();

 // Update each product's CategoryID
 foreach (Northwind.ProductsRow product in products)
 {
 product.CategoryID = product.ProductID;
 }

 // Update the data WITHOUT using a transaction
 NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
 new NorthwindTableAdapters.ProductsTableAdapter();
 productsAdapter.Update(products);

 // Refresh the Grid
 Products.DataBind();
}

 

  refresh按鈕的Click事件處理器僅僅調用Products GridView的DataBind方法將數據重新綁定到ridView控件.

  第二個事件處理器對products的CategoryID屬性重新賦值,并調用BLL層里的新的事務方法來執行數據庫更新.我們注意到將每個產品的ProductID值賦給其CategoryID屬性,對最開頭的幾個產品而言沒有任何問題,但隨著ProductID值越變越大,CategoryID的值也越變越大,而Category表里定義的種類畢竟有限,于是問題就出來了。

  第三個事件處理器也是將ProductID值賦給CategoryID屬性,只是用ProductsTableAdapter的默認的Update方法來更新數據庫. 該Update方法并沒有使用事務來封裝這些命令,所以只要是沒有違背外鍵約束的更新都會執行成功.

  在瀏覽器里登錄該頁面進行驗證.最開始你將看到如圖8所示的畫面,然后點“Modify Categories (WITH TRANSACTION)”.這將導致頁面回傳并試題更新所有products的CategoryID值,這將導致違背外鍵約束(見圖9).


圖8:Products將顯示在一個分頁的GridView控件里


圖9:導致違背外鍵約束

  現在點擊瀏覽器的Back按鈕,再點擊“Refresh Grid”按鈕,此時你看到的界面和圖8的界面一摸一樣。這是因為發生了違背外鍵約束,導致回滾,所有的操作失敗.

  再點“Modify Categories (WITHOUT TRANSACTION)”按鈕,這同樣將違背外鍵約束(見圖9),不過這一次,那些對CategoryID屬性賦以有效值的操作不會回滾.點擊瀏覽器的Back按鈕,再點“Refresh Grid”按鈕。就像圖10顯示的那樣,最開始的8個產品的CategoryID值已經發生了更改,比如,在圖8里Chang的CategoryID值為1,而在圖10里就變成了2了.


圖10:某些Product的CategoryID值發生了改變,而其它的沒有

結語:

  默認情況下,TableAdapter的方法沒有使用事務來執行數據庫命令,不過只需多做一點工作我們就可以添加一些用于創建、提交、回滾事務的方法.在本教程,我們在ProductsTableAdapter class類里創建了這3個方法:BeginTransaction, CommitTransaction,和RollbackTransaction.我們考察了如何在try...catch模塊里使用這些方法來執行一系列的修改命令.具體來說,我們在ProductsTableAdapter里創建了UpdateWithTransaction方法,該方法運用Batch Update模式對ProductsDataTable里的每行記錄執行必要的更改操作;我們也對BLL里的ProductsBLL class類添加了DeleteProductsWithTransaction方法,它將一系列ProductID值作為輸入參數,并使用DB-Direct模式將每個產品刪除.這些方法開始都創建一個事務,再在try...catch模塊里執行數據更改命令.如果拋出異常,則回滾事務,否則提交事務.

  第五步演示了事務的作用。在接下來的3章我們將以本章為基礎,創建批更新、批刪除、批添加的用戶界面.

  祝編程快樂!

作者簡介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用 微軟Web技術。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數據教程》,希望對大家的學習ASP.NET有所幫助。

您可能感興趣的文章:
  • 在ASP.NET 2.0中操作數據之五十九:使用SQL緩存依賴項SqlCacheDependency
  • 在ASP.NET 2.0中操作數據之六十:創建一個自定義的Database-Driven Site Map Provider
  • 在ASP.NET 2.0中操作數據之六十二:GridView批量更新數據
  • 在ASP.NET 2.0中操作數據之六十三:GridView實現批量刪除數據
  • 在ASP.NET 2.0中操作數據之六十四:GridView批量添加數據
  • 在ASP.NET 2.0中操作數據之六十五:在TableAdapters中創建新的存儲過程
  • 在ASP.NET 2.0中操作數據之六十六:在TableAdapters中使用現有的存儲過程
  • 在ASP.NET 2.0中操作數據之六十七:在TableAdapters中使用JOINs
  • 在ASP.NET 2.0中操作數據之六十八:為DataTable添加額外的列
  • 在ASP.NET 2.0中操作數據之六十九:處理Computed Columns列

標簽:聊城 海西 平涼 中衛 清遠 甘肅 慶陽 臨夏

巨人網絡通訊聲明:本文標題《在ASP.NET 2.0中操作數據之六十一:在事務里對數據庫修改進行封裝》,本文關鍵詞  在,ASP.NET,2.0,中,操作,數據,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《在ASP.NET 2.0中操作數據之六十一:在事務里對數據庫修改進行封裝》相關的同類信息!
  • 本頁收集關于在ASP.NET 2.0中操作數據之六十一:在事務里對數據庫修改進行封裝的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    99久久亚洲一区二区三区青草| 高清国产一区二区| 色狠狠一区二区三区香蕉| 亚洲视频一区二区在线观看| 99久久国产综合精品色伊| 久久国产精品区| 午夜久久福利影院| 久久久久久久久久久黄色| 成人va在线观看| 亚洲国产精品久久不卡毛片| 精品国产一区二区三区忘忧草| 91在线观看地址| 国产成人精品影院| 亚洲一区二区av在线| 北条麻妃国产九九精品视频| 国产精品电影一区二区三区| 日本一区二区综合亚洲| 亚洲欧美偷拍三级| 日韩电影一二三区| 丰满放荡岳乱妇91ww| 91国偷自产一区二区三区成为亚洲经典| 欧美人牲a欧美精品| 2022国产精品视频| 99re这里都是精品| 精品福利一区二区三区| 日韩一级大片在线观看| 日韩经典中文字幕一区| 偷拍自拍另类欧美| 日韩高清一级片| 欧美日韩国产综合一区二区三区| 亚洲精品videosex极品| 日韩欧美国产高清| 国产午夜精品久久久久久久 | 综合激情网...| 亚洲美女在线国产| 黑人精品欧美一区二区蜜桃| 99国产精品久久久| 亚洲成人三级小说| 国产乱码精品一区二区三区五月婷| 中文字幕欧美一| 久久精品免费观看| av在线不卡观看免费观看| 成人久久视频在线观看| 国产精品色在线| 亚洲欧美日韩综合aⅴ视频| 一区二区高清视频在线观看| 欧美色成人综合| 精品无人码麻豆乱码1区2区| 久久久影视传媒| 色丁香久综合在线久综合在线观看| 成人午夜在线播放| 丁香天五香天堂综合| 日本韩国精品一区二区在线观看| 一本到不卡免费一区二区| 91精品在线免费| 青青草91视频| 久久久欧美精品sm网站| 国产乱对白刺激视频不卡| 中文字幕av一区二区三区高 | 91麻豆精品久久久久蜜臀| 欧美亚洲另类激情小说| 欧美日韩日本视频| 日本在线观看不卡视频| 26uuu另类欧美亚洲曰本| 欧美日韩亚洲综合在线| 视频在线观看一区| 一区二区三区在线视频观看58| 久久久精品黄色| 久久婷婷成人综合色| 99这里只有精品| 中文字幕中文字幕中文字幕亚洲无线| 在线看一区二区| 在线亚洲+欧美+日本专区| 日本一区二区动态图| 中文字幕第一区综合| 日本不卡不码高清免费观看| 不卡一区中文字幕| 久久伊99综合婷婷久久伊| 亚洲午夜免费视频| 成人一区二区视频| 精品国产一区二区国模嫣然| 亚洲成人第一页| 在线观看视频一区二区欧美日韩| 国产精品萝li| 成人免费看片app下载| 亚洲精品一区二区三区精华液| 亚洲国产精品自拍| 91成人网在线| 中文字幕欧美一区| 91免费版pro下载短视频| 久久亚洲一区二区三区明星换脸| 美女www一区二区| 欧美日韩aaaaa| 婷婷国产v国产偷v亚洲高清| 成人av资源网站| 国产精品美女久久久久久久久久久| 亚洲国产精品久久不卡毛片| 国产激情偷乱视频一区二区三区| 91精品国产综合久久蜜臀| 亚洲一区免费在线观看| 色菇凉天天综合网| 一色屋精品亚洲香蕉网站| 91视视频在线观看入口直接观看www | 精品久久国产97色综合| 亚洲男女一区二区三区| av在线不卡网| 亚洲三级视频在线观看| 成人av在线资源网| 26uuu国产电影一区二区| 国产在线一区二区| 26uuu精品一区二区三区四区在线| 日本aⅴ免费视频一区二区三区| 欧美日韩另类一区| 五月天网站亚洲| 欧美日韩在线电影| 日日夜夜精品免费视频| 欧美三级视频在线| 日本最新不卡在线| 精品对白一区国产伦| 亚洲超丰满肉感bbw| 欧美日韩黄视频| 性做久久久久久久免费看| 欧美精品tushy高清| 天堂资源在线中文精品| 欧美日韩一区二区三区在线看| 亚洲国产aⅴ成人精品无吗| 国产精品久久久久久久久免费相片| 韩国女主播成人在线| 国产亚洲成年网址在线观看| 国产成人精品亚洲777人妖| 欧美精品日韩一区| 亚洲国产精品精华液网站| 日韩三区在线观看| 激情图片小说一区| 国产精品激情偷乱一区二区∴| 高清不卡一二三区| 亚洲精品免费看| 日韩精品中文字幕在线不卡尤物| 国产伦精一区二区三区| 国产精品久久久久影院色老大| 国产伦精品一区二区三区在线观看 | 欧美成人bangbros| 国产成人在线视频免费播放| 亚洲天天做日日做天天谢日日欢 | 国产精品久久久久四虎| 欧美综合天天夜夜久久| 亚洲一区二区视频在线| 91精品国产aⅴ一区二区| 免费观看91视频大全| 日韩免费电影网站| 99亚偷拍自图区亚洲| 亚洲线精品一区二区三区| 69久久99精品久久久久婷婷 | 久久嫩草精品久久久久| 97精品电影院| 国产一区二区三区免费看| 亚洲一区二区三区视频在线| 久久久久国产精品麻豆ai换脸| 91免费视频网址| 久久国产日韩欧美精品| 午夜精品久久久久久久久| 欧美激情在线一区二区| 欧美一区二区三区成人| 处破女av一区二区| 人人爽香蕉精品| 亚洲一区二区三区不卡国产欧美| 99久久伊人精品| 亚洲午夜成aⅴ人片| 欧美亚洲日本一区| 91看片淫黄大片一级在线观看| 国产精品一二三四区| 麻豆精品一区二区| www.亚洲色图| 亚洲成va人在线观看| 欧美午夜精品久久久久久孕妇 | 久久久久久久久久久久久夜| 国产精品一品视频| 伊人夜夜躁av伊人久久| 在线观看国产精品网站| 亚洲成人在线观看视频| 欧美亚洲国产一区在线观看网站| 国产成人在线网站| 尤物在线观看一区| 日韩精品一区国产麻豆| 国产suv一区二区三区88区| 久久日一线二线三线suv| 99久久综合色| 麻豆国产欧美一区二区三区| 中文字幕欧美国产| 麻豆免费看一区二区三区| 精品国产露脸精彩对白| 欧洲av一区二区嗯嗯嗯啊| 免费在线观看不卡| 久久亚洲私人国产精品va媚药| 成人深夜视频在线观看| 奇米色一区二区| 亚洲精品中文在线影院| 欧美r级在线观看| 欧美日韩国产一级| 菠萝蜜视频在线观看一区|