国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - ASP.NET教程 - 在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)

2020-01-09 13:56heker2007 ASP.NET教程

前面幾節(jié)我們講解了ASP.NET中如何上傳顯示二進制圖片數(shù)據(jù),這一節(jié)我們來介紹一下如何在GridView編輯和刪除已經(jīng)存在的二進制數(shù)據(jù)。

導(dǎo)言:

  在前面的3章里我們?yōu)樘幚矶M制數(shù)據(jù)添加了很多的功能。我們首先在表Categories里添加BrochurePath列,并更新了體系結(jié)構(gòu)。同樣,為了處理表Categorie里現(xiàn)有的Picture列,我們在數(shù)據(jù)訪問層和業(yè)務(wù)邏輯層里增加了相應(yīng)的方法。同時我們創(chuàng)建一個頁面,在GridView控件里顯示二進制數(shù)據(jù)——包含一個指向說明小冊子的下載鏈接,并將每個類的圖片顯示在<img>元素里。同時我們添加一個DetailsView控件,供用戶添加新的類,并上傳其圖片和小冊子數(shù)據(jù)。

  剩下的就是添加編輯和刪除功能,本章我們將通過GridView控件內(nèi)建的編輯和刪除功能來實現(xiàn)。當(dāng)編輯一個類時,我們允許用戶用任意指定的圖片將原來的換掉;也可以用新的小冊子將現(xiàn)有的替換掉,甚至不再包含小冊子文件。讓我們開始吧!

第1步:更新數(shù)據(jù)訪問層

  雖然數(shù)據(jù)訪問層包含自動生成的Insert, Update和Delete方法,但它們都基于CategoriesTableAdapter的主查詢,因此并不包含Picture列。自然,Insert和Update方法也不包含picture列的相應(yīng)參數(shù)。就像56章做的那樣,我們需要為更新Categories表而創(chuàng)建新的TableAdapter方法。

  右鍵點擊CategoriesTableAdapter的頂部,選擇“添加查詢”,打開TableAdapter查詢設(shè)置向?qū)В覀兪紫冗x擇“使用SQL語句”,點Next,再選“UPDATE”,再點Next.

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖1:選擇“UPDATE”選項

我們現(xiàn)在需要指定UPDATE SQL語句。向?qū)ё詣觿?chuàng)建一個基于TableAdapter主查詢的UPDATE語句(它更新CategoryName, Description和BrochurePath值)。更新該語句以包含Picture列,以及@Picture參數(shù),像如下這樣:

?
1
2
3
4
5
6
UPDATE [Categories] SET
 [CategoryName] = @CategoryName,
 [Description] = @Description,
 [BrochurePath] = @BrochurePath ,
 [Picture] = @Picture
WHERE (([CategoryID] = @Original_CategoryID))

最后,向?qū)б笪覀優(yōu)樾碌腡ableAdapter方法命名,我們?nèi)閁pdateWithPicture,再點Finish。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖2:為新方法命名為UpdateWithPicture

第2步:添加新的業(yè)務(wù)邏輯方法

除了更新DAL外,我們需要更新BLL以包含更新、刪除類的方法。以下是表現(xiàn)層需要調(diào)用的方法:

為了刪除一個類,我們使用CategoriesTableAdapter的自動生成的Delete方法,在類CategoriesBLL里添加如下的方法:

?
1
2
3
4
5
6
7
8
9
[System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Delete, true)]
public bool DeleteCategory(int categoryID)
{
 int rowsAffected = Adapter.Delete(categoryID);
 
 // Return true if precisely one row was deleted, otherwise false
 return rowsAffected == 1;
}<br>

  本教程,為了更新一個類,我們將創(chuàng)建2個方法。一個方法接受picture值,并調(diào)用我們剛剛添加到CategoriesTableAdapter里的UpdateWithPicture方法。另一個方法只接受CategoryName, Description和BrochurePath值, 并調(diào)用CategoriesTableAdapter類里自動生成的Update語句。為什么要使用2種方法呢?某些情況下,用戶更新類時同時更新其圖片,這時就需要上傳一張新圖片。上傳圖片的數(shù)據(jù)將在UPDATE語句里用到;另一種情況,用戶只想更新類的name和description信息,因此我們需要使用2種更新方法。業(yè)務(wù)邏輯層會根據(jù)是否傳入picture值來判斷使用哪種方法。

  為達該目的,我們要在CategoriesBLL類里添加2個方法,名字都是UpdateCategory,第一個方法接受的參數(shù)包括3個string,1個byte數(shù)組和1個int;第二個方法接受的參數(shù)包括3個string和1個int。3個字符串參數(shù)代表類的name, description和brochure文件路徑,byte數(shù)組包含的是類的picture數(shù)據(jù),int代表類記錄的CategoryID,我們注意到,當(dāng)傳入的byte數(shù)組為null時,第一個方法將調(diào)用第二個方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Update, false)]
public bool UpdateCategory(string categoryName, string description,
 string brochurePath, byte[] picture, int categoryID)
{
 // If no picture is specified, use other overload
 if (picture == null)
 return UpdateCategory(categoryName, description, brochurePath, categoryID);
 
 // Update picture, as well
 int rowsAffected = Adapter.UpdateWithPicture
 (categoryName, description, brochurePath, picture, categoryID);
 
 // Return true if precisely one row was updated, otherwise false
 return rowsAffected == 1;
}
 
[System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Update, true)]
public bool UpdateCategory(string categoryName, string description,
 string brochurePath, int categoryID)
{
 int rowsAffected = Adapter.Update
 (categoryName, description, brochurePath, categoryID);
 
 // Return true if precisely one row was updated, otherwise false
 return rowsAffected == 1;
}

第3步:拷貝功能

  在上一章里,我們創(chuàng)建了一個UploadInDetailsView.aspx頁面,在一個GridView控件列出所有的類,再通過一個DetailsView控件來添加新的類。在本教程,我們將擴展GridView控件以支持編輯和刪除功能。不過我們不再使用UploadInDetailsView.aspx頁面,讓我們在~/BinaryData文件夾里創(chuàng)建一個新頁面,UpdatingAndDeleting.aspx,將UploadInDetailsView.aspx頁面的聲明代碼復(fù)制并粘貼到頁面UpdatingAndDeleting.aspx.

  打開UploadInDetailsView.aspx頁面,將其<asp:Content>元素里的聲明代碼復(fù)制下來,就像圖3那樣。接下來,打開UpdatingAndDeleting.aspx頁面,把代碼粘貼在<asp:Content>元素里。同樣的,將UploadInDetailsView.aspx頁面的后臺代碼拷貝到UpdatingAndDeleting.aspx。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖3:將UploadInDetailsView.aspx頁面的聲明代碼拷貝下來

完成后,登錄UpdatingAndDeleting.aspx頁面,你將會看到相同的輸出效果。感覺用起來和UploadInDetailsView.aspx頁面一樣。

第4步:添加ObjectDataSource和GridView的刪除功能

  就像在教程16《概述插入、更新和刪除數(shù)據(jù)》里探討的一樣,只要GridView控件綁定的數(shù)據(jù)源支持“刪除”功能,我們就可以為GridView控件啟用刪除功能。不過,GridView控件綁定的ObjectDataSource(也就是CategoriesDataSource)目前并不支持刪除。

  為支持刪除,在ObjectDataSource的智能標(biāo)簽里點“配置數(shù)據(jù)源”,一直點到“定義數(shù)據(jù)方法”界面。雖然當(dāng)前只指定了ObjectDataSource控件InsertMethod屬性和SelectMethod屬性,但向?qū)ё詣拥胤謩e為UPDATE標(biāo)簽和DELETE標(biāo)簽指定UpdateCategory方法和DeleteCategory方法。為什么呢?因為我們在CategoriesBLL類里為上述2種方法使用了DataObjectMethodAttribute屬性,作用是分別使其成為默認的“更新”和“刪除”方法。

  不過現(xiàn)在我們在UPDATE標(biāo)簽的下拉列表里選“(None)”, 而 DELETE標(biāo)簽里仍然為DeleteCategory方法。我們將在第6步添加更新功能。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖4:設(shè)置ObjectDataSource控件使用DeleteCategory方法

  注意:完成設(shè)置后,Visual Studio會問你是否“刷新列和主鍵”,選擇No,因為選擇Yes將會把我們自己定制的任何列覆蓋掉。

  現(xiàn)在,ObjectDataSource控件將包含DeleteMethod屬性和對應(yīng)的DeleteParameter參數(shù)。我們記得在以前的教程提到過,當(dāng)使用向?qū)е付ǚ椒〞r,Visual Studio會自動的將ObjectDataSource控件的OldValuesParameterFormatString屬性設(shè)置為original_{0},這將導(dǎo)致更新和刪除時出現(xiàn)問題。為此,要么將清除該屬性,要么將其設(shè)置為默認的{0}值。對該屬性的更詳細討論見教程16《概述插入、更新和刪除數(shù)據(jù)》

完成后,ObjectDataSource控件的聲明代碼看起來應(yīng)該像下面的一樣:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
 OldValuesParameterFormatString="{0}" SelectMethod="GetCategories"
 TypeName="CategoriesBLL" InsertMethod="InsertWithPicture"
 DeleteMethod="DeleteCategory">
 <InsertParameters>
 <asp:Parameter Name="categoryName" Type="String" />
 <asp:Parameter Name="description" Type="String" />
 <asp:Parameter Name="brochurePath" Type="String" />
 <asp:Parameter Name="picture" Type="Object" />
 </InsertParameters>
 <DeleteParameters>
 <asp:Parameter Name="categoryID" Type="Int32" />
 </DeleteParameters>
</asp:ObjectDataSource>

設(shè)置完ObjectDataSource后,就可以啟用GridView的刪除功能了,方法是點擊其智能標(biāo)簽里的“刪除選項”。這將使GridView增加一個CommandField,其ShowDeleteButton屬性為true。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖5:啟用GridView控件的刪除功能

  花幾分鐘測試刪除功能。由于表Products和表Categories之間有一個外鍵CategoryID,當(dāng)你刪除現(xiàn)有的8個類中的任何一個時,你會得到一個外鍵約束沖突異常。為順利的實現(xiàn)測試,我們需要添加一個附帶圖片和說明小冊子的新類,如圖6所示,小冊子為Test.pdf,圖7為添加了測試類的GridView控件界面。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖6:添加一個附帶Brochure和Image文件的測試類

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖7:添加測試類后,顯示在GridView控件里

在Visual Studio里刷新解決資源管理器,你會在文件夾~/Brochures里看到Test.pdf文件(見圖8)

下一步,點擊Test類的Delete鏈接,頁面回傳,引發(fā)CategoriesBLL的DeleteCategory 方法,該方法又調(diào)用DAL層的Delete方法,向數(shù)據(jù)庫發(fā)送適當(dāng)?shù)腄ELETE命令。最后數(shù)據(jù)重新綁定到GridView控件,Test類將不再顯示出來。

雖然已經(jīng)成功地將Test類從Categories表刪除,但存儲在文件系統(tǒng)的對應(yīng)小冊子仍舊存在,刷新解決資源管理器,你將發(fā)現(xiàn)Test.pdf依然放在~/Brochures文件夾里。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖8:Test.pdf文件并沒有從文件系統(tǒng)刪除

第5步:刪除殘存的Brochure文件

  未將二進制數(shù)據(jù)存儲進數(shù)據(jù)庫時面臨的一個問題便是:當(dāng)刪除一條數(shù)據(jù)庫記錄時,我們需要另外采取步驟來刪除該記錄對應(yīng)的二進制數(shù)據(jù)文件。當(dāng)執(zhí)行delete命令時,會發(fā)生一些事前事件和事后事件(pre- and post-action events),我們需要創(chuàng)建對應(yīng)的事件處理器。在Categories表的記錄被刪除之前,我們需要確定對應(yīng)PDF文件的路徑,但在刪除記錄之前我們不會刪除其對應(yīng)的PDF文件,以防發(fā)生異常或記錄最終未被刪除的情況。

  從事件發(fā)生的時間先后順序來看,GridView控件的RowDeleting事件在調(diào)用ObjectDataSource控件的delete命令前發(fā)生;而RowDeleted事件在調(diào)用ObjectDataSource控件的delete命令之后再發(fā)生。創(chuàng)建這2個事件處理器,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// A page variable to "remember" the deleted category's BrochurePath value
string deletedCategorysPdfPath = null;
 
protected void Categories_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
 // Determine the PDF path for the category being deleted...
 int categoryID = Convert.ToInt32(e.Keys["CategoryID"]);
 
 CategoriesBLL categoryAPI = new CategoriesBLL();
 Northwind.CategoriesDataTable categories =
 categoryAPI.GetCategoryByCategoryID(categoryID);
 Northwind.CategoriesRow category = categories[0];
 
 if (category.IsBrochurePathNull())
 deletedCategorysPdfPath = null;
 else
 deletedCategorysPdfPath = category.BrochurePath;
}
 
protected void Categories_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
 // Delete the brochure file if there were no problems deleting the record
 if (e.Exception == null)
 {
 // Is there a file to delete?
 if (deletedCategorysPdfPath != null)
 {
  System.IO.File.Delete(Server.MapPath(deletedCategorysPdfPath));
 }
 }
}

  在RowDeleting事件處理器里,從GridView控件的DataKeys集合里獲取被刪記錄的CategoryID值,而在這里,我們通過e.Keys來訪問DataKeys集合。接著,調(diào)用類CategoriesBLL的GetCategoryByCategoryID(categoryID)方法來返回被刪記錄的信息,若返回的BrochurePath值不為NULL,那么將其賦值給頁面參數(shù)deletedCategorysPdfPath,再在RowDeleted事件處理器里刪除文件。

  注意:在RowDeleting事件處理器里,我們沒有返回被刪記錄的BrochurePath信息,而是將BrochurePath添加到GridView的DataKeyNames屬性,再通過訪問e.Keys來獲取該記錄的值。這樣做雖然稍微增大了GridView的視圖狀態(tài),但減少了必要的代碼,也省了一步訪問數(shù)據(jù)庫。

  調(diào)用ObjectDataSource控件的delete命令后,緊接著發(fā)生GridView控件的RowDeleted事件,如果刪除過程沒有異常且deletedCategorysPdfPath值不為空,那就將對應(yīng)的PDF文件從文件系統(tǒng)刪除。我們注意到,代碼沒有刪除類的picture,那是因為picture數(shù)據(jù)是直接存儲在數(shù)據(jù)庫里的,當(dāng)刪除記錄時就一起刪除了。

  添加完上述2個事件處理器后,再次測試刪除。當(dāng)刪除某個類時,其對應(yīng)的PDF文件也刪除了。

  下面我們深入研究添加更新功能以應(yīng)對類的brochure和picture.第6步探討更新brochure信息的技術(shù),第7章探討更新picture。

第6步:更新類的Brochure

  就像在教程16《概述插入、更新和刪除數(shù)據(jù)》里探討的一樣,如果GridView的數(shù)據(jù)源控件支持編輯,那么我們就可以啟用GridView控件的編輯功能。當(dāng)前,名為CategoriesDataSource的ObjectDataSource控件并不支持編輯,那讓我們添加吧。

  點擊ObjectDataSource控件的“設(shè)置數(shù)據(jù)源”鏈接,一直點到“定義數(shù)據(jù)方法”界面。由于在CategoriesBLL里對重載的UpdateCategory方法使用了DataObjectMethodAttribute屬性,UPDATE標(biāo)簽的下拉列表自動的選擇了該方法,它包含4個輸入?yún)?shù)(不包含Picture)。我們選擇另一個包含5個輸入?yún)?shù)的重載的UpdateCategory方法。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖9:設(shè)置ObjectDataSource控件使用包含Picture參數(shù)的UpdateCategory方法

  ObjectDataSource控件現(xiàn)在包含了UpdateMethod屬性以及相應(yīng)的UpdateParameters參數(shù)集。就像在第4步提到的一樣,當(dāng)使用設(shè)置向?qū)r,Visual Studio會將ObjectDataSource控件的OldValuesParameterFormatString屬性設(shè)置為original_{0},這導(dǎo)致調(diào)用update和delete方法時出現(xiàn)問題。因此,要么將該屬性清除,要么設(shè)該屬性為{0}。

完成后,ObjectDataSource控件的聲明代碼看起來應(yīng)該和下面的差不多:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
 OldValuesParameterFormatString="{0}" SelectMethod="GetCategories"
 TypeName="CategoriesBLL" InsertMethod="InsertWithPicture"
 DeleteMethod="DeleteCategory" UpdateMethod="UpdateCategory">
 <InsertParameters>
 <asp:Parameter Name="categoryName" Type="String" />
 <asp:Parameter Name="description" Type="String" />
 <asp:Parameter Name="brochurePath" Type="String" />
 <asp:Parameter Name="picture" Type="Object" />
 </InsertParameters>
 <DeleteParameters>
 <asp:Parameter Name="categoryID" Type="Int32" />
 </DeleteParameters>
 <UpdateParameters>
 <asp:Parameter Name="categoryName" Type="String" />
 <asp:Parameter Name="description" Type="String" />
 <asp:Parameter Name="brochurePath" Type="String" />
 <asp:Parameter Name="picture" Type="Object" />
 <asp:Parameter Name="categoryID" Type="Int32" />
 </UpdateParameters>
</asp:ObjectDataSource>

要啟用編輯功能,從GridView控件的智能標(biāo)簽里選“編輯”。這將設(shè)置CommandField的ShowEditButton屬性為true,結(jié)果是為每行添加一個Edit按鈕(當(dāng)記錄處于編輯狀態(tài)時,將呈現(xiàn)為Update和Cancel按鈕)

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖10:啟用GridView控件的編輯功能

  從瀏覽器查看該頁面,點某條記錄的Edit按鈕。CategoryName和Description列呈現(xiàn)為一個文本框。由于BrochurePath TemplateField沒有EditItemTemplate模板,所以它依舊呈現(xiàn)其ItemTemplate模板——一個指向brochure的鏈接。Picture列呈現(xiàn)為一個文本框,并且該Picture ImageField的Text屬性被指派為DataImageUrlField值,在這里,即CategoryID.

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖11:BrochurePath列沒有編輯界面

定制BrochurePath編輯界面

我們可以為BrochurePath TemplateField創(chuàng)建一個編輯界面,我們可以選擇:

.維持原樣
.上傳新的brochure以作更新
.將brochure刪除(這樣一來,類就沒有對應(yīng)的brochure了)

我們也應(yīng)該更新Picture ImageField的編輯界面,不過我們將放在第7步來討論。

  在GridView控件的智能標(biāo)簽里選擇“編輯模板”,再從下拉列表里選BrochurePath TemplateField的EditItemTemplate模板。在模板里添加一個RadioButtonList Web控件,其ID為BrochureOptions;AutoPostBack屬性為true.再在屬性窗口里點Items屬性的橢圓型區(qū)域,進入ListItem Collection Editor界面,分別添加值為1,2,3的選項:

.Use current brochure
.Remove current brochure
.Upload new brochure

設(shè)第一個ListItem的Selected屬性為true.

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖12:為RadioButtonList控件添加3個ListItems

在RadioButtonList控件下面,添加一個FileUpload控件,ID為BrochureUpload,設(shè)其Visible屬性為false。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖13:在EditItemTemplate模板里添加RadioButtonList和FileUpload控件

RadioButtonList控件為用戶提供了3個選擇,只有當(dāng)選擇“Upload new brochure”時, FileUpload控件才會展現(xiàn)出來。為此,我們?yōu)镽adioButtonList控件的SelectedIndexChanged事件創(chuàng)建事件處理器,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void BrochureOptions_SelectedIndexChanged(object sender, EventArgs e)
{
 // Get a reference to the RadioButtonList and its Parent
 RadioButtonList BrochureOptions = (RadioButtonList)sender;
 Control parent = BrochureOptions.Parent;
 
 // Now use FindControl("controlID") to get a reference of the
 // FileUpload control
 FileUpload BrochureUpload =
 (FileUpload)parent.FindControl("BrochureUpload");
 
 // Only show BrochureUpload if SelectedValue = "3"
 BrochureUpload.Visible = (BrochureOptions.SelectedValue == "3");
}

  由于RadioButtonList控件和FileUpload控件同時出現(xiàn)在一個模板里,我們需要通過編程來訪問這2個控件。在SelectedIndexChanged事件處理器里,我們通過輸入?yún)?shù)sender來引用RadioButtonList控件。為了獲取FileUpload控件,我們需要使用RadioButtonList的父控件(parent control),并使用FindControl("controlID")方法。一旦我們同時獲取了RadioButtonList和FileUpload控件時,只要RadioButtonList控件的SelectedValue值等于3,即“Upload new brochure” ListItem的值時,將FileUpload控件的Visible屬性設(shè)置為true 。

  添加完上述代碼后,花幾分鐘時間來測試編輯頁面。點擊某行的Edit按鈕,默認是選中“Use current brochure”項,改選另一項,頁面產(chǎn)生回傳,如果是選擇第3項,則FileUpload控件將會顯示出來,否則處于隱身狀態(tài)。圖14顯示點擊Edit按鈕的情形,而圖15則是選擇“Upload new brochure”時的情形。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖14:默認選擇“Use current brochure”項

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖15:選擇“Upload new brochure”時FileUpload控件顯示出來

保存Brochure文件并更新BrochurePath列

當(dāng)點擊GridView控件的Update按鈕時,觸發(fā)RowUpdating事件,調(diào)用ObjectDataSource控件的update命令,然后觸發(fā)GridView控件的RowUpdated事件。跟deleting流程類似,我們需要創(chuàng)建這些事件的處理器。在RowUpdating事件處理器里,我們需要根據(jù)RadioButtonList的SelectedValue值來判斷下一步怎么做。

.如果SelectedValue值為1,我們將保持rochurePath不變。所以我們將ObjectDataSource控件的brochurePath參數(shù)設(shè)置為當(dāng)前處于編輯狀態(tài)記錄的BrochurePath值,方法為e.NewValues["brochurePath"] = value.

.如果SelectedValue值為2,意味著將BrochurePath設(shè)為NULL。為此,我們需要將ObjectDataSource控件的brochurePath參數(shù)設(shè)為Nothing,結(jié)果就是在UPDATE命令里使用NULL。如果存在對應(yīng)的brochure文件,我們必須將其刪除,前提是沒有拋出任何的異常。

.如果SelectedValue值為3,我們必須確保用戶已經(jīng)上傳了一個PDF文件并將其保存在文件系統(tǒng),然后更新記錄的BrochurePath值。我們要先將被替換的前一個文件刪除掉,當(dāng)然前提是沒有引發(fā)異常。

在上一章里,當(dāng)在DetailsView控件里添加新記錄時,觸發(fā)DetailsView控件的ItemInserting事件。在本章,當(dāng)RadioButtonList控件的SelectedValue為3時(即我們選擇Upload new brochure時),接下來要采取的步驟實際上與DetailsView控件的ItemInserting事件處理器實現(xiàn)的功能相似。根據(jù)實現(xiàn)的功能,我劃分為2個方法:

.ProcessBrochureUpload(FileUpload, out bool):它以一個FileUpload控件實例為輸入?yún)?shù),結(jié)果為一個布爾值(Boolean)。根據(jù)該布爾值判斷是否繼續(xù)更新或刪除操作,抑或取消操作。如果存在上傳文件該方法就返回其路徑,反之返回null。

.DeleteRememberedBrochurePath:如果頁面變量deletedCategorysPdfPath不為null,則刪除該參數(shù)指定的文件。

下面是上述2種方法的代碼。注意ProcessBrochureUpload方法和DetailsView控件的ItemInserting事件處理器有某些相似性,在本章,我們更新DetailsView控件的事件處理器以使用這些新方法。下載本章的代碼,查看我們對DetailsView控件的事件處理器所做的修改。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private string ProcessBrochureUpload
 (FileUpload BrochureUpload, out bool CancelOperation)
{
 CancelOperation = false; // by default, do not cancel operation
 
 if (BrochureUpload.HasFile)
 {
 // Make sure that a PDF has been uploaded
 if (string.Compare(System.IO.Path.GetExtension(BrochureUpload.FileName),
  ".pdf", true) != 0)
 {
  UploadWarning.Text =
  "Only PDF documents may be used for a category's brochure.";
  UploadWarning.Visible = true;
  CancelOperation = true;
  return null;
 }
 
 const string BrochureDirectory = "~/Brochures/";
 string brochurePath = BrochureDirectory + BrochureUpload.FileName;
 string fileNameWithoutExtension =
  System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName);
 
 int iteration = 1;
 
 while (System.IO.File.Exists(Server.MapPath(brochurePath)))
 {
  brochurePath = string.Concat(BrochureDirectory, fileNameWithoutExtension,
  "-", iteration, ".pdf");
  iteration++;
 }
 
 // Save the file to disk and set the value of the brochurePath parameter
 BrochureUpload.SaveAs(Server.MapPath(brochurePath));
 return brochurePath;
 }
 else
 {
 // No file uploaded
 return null;
 }
}
 
private void DeleteRememberedBrochurePath()
{
 // Is there a file to delete?
 if (deletedCategorysPdfPath != null)
 {
 System.IO.File.Delete(Server.MapPath(deletedCategorysPdfPath));
 }
}

在GridView控件的RowUpdating和RowUpdated事件處理器里使用上面2個方法,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
protected void Categories_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
 // Reference the RadioButtonList
 RadioButtonList BrochureOptions =
 (RadioButtonList)Categories.Rows[e.RowIndex].FindControl("BrochureOptions");
 
 // Get BrochurePath information about the record being updated
 int categoryID = Convert.ToInt32(e.Keys["CategoryID"]);
 
 CategoriesBLL categoryAPI = new CategoriesBLL();
 Northwind.CategoriesDataTable categories =
 categoryAPI.GetCategoryByCategoryID(categoryID);
 Northwind.CategoriesRow category = categories[0];
 
 if (BrochureOptions.SelectedValue == "1")
 {
 // Use current value for BrochurePath
 if (category.IsBrochurePathNull())
  e.NewValues["brochurePath"] = null;
 else
  e.NewValues["brochurePath"] = category.BrochurePath;
 }
 else if (BrochureOptions.SelectedValue == "2")
 {
 // Remove the current brochure (set it to NULL in the database)
 e.NewValues["brochurePath"] = null;
 }
 else if (BrochureOptions.SelectedValue == "3")
 {
 // Reference the BrochurePath FileUpload control
 FileUpload BrochureUpload =
  (FileUpload)Categories.Rows[e.RowIndex].FindControl("BrochureUpload");
 
 // Process the BrochureUpload
 bool cancelOperation = false;
 e.NewValues["brochurePath"] =
  ProcessBrochureUpload(BrochureUpload, out cancelOperation);
 
 e.Cancel = cancelOperation;
 }
 else
 {
 // Unknown value!
 throw new ApplicationException(
  string.Format("Invalid BrochureOptions value, {0}",
  BrochureOptions.SelectedValue));
 }
 
 if (BrochureOptions.SelectedValue == "2" ||
 BrochureOptions.SelectedValue == "3")
 {
 // "Remember" that we need to delete the old PDF file
 if (category.IsBrochurePathNull())
  deletedCategorysPdfPath = null;
 else
  deletedCategorysPdfPath = category.BrochurePath;
 }
}
 
protected void Categories_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
 // If there were no problems and we updated the PDF file,
 // then delete the existing one
 if (e.Exception == null)
 {
 DeleteRememberedBrochurePath();
 }
}

注意:RowUpdating事件處理器是如何根據(jù)SelectedValue值的不同而使用一系列的條件語句來實現(xiàn)相應(yīng)的功能。

使用上面的代碼,我們就可以編輯一個類了,使用其當(dāng)前的brochure,或不使用brochure,再或者使用一個新的brochure。在RowUpdating和RowUpdated事件處理器里設(shè)置斷點(breakpoints)吧,以便更好的理解處理流程。

第7步:上傳新圖片

  Picture ImageField的編輯界面呈現(xiàn)為一個文本框,里面顯示的是DataImageUrlField 屬性的值。在編輯流程,GridView控件向ObjectDataSource傳入一個參數(shù),參數(shù)名為ImageField的DataImageUrlField屬性;參數(shù)值為在編輯界面輸入文本框里的值。當(dāng)圖片是存儲在文件系統(tǒng),且DataImageUrlField屬性包含的是訪問該圖片的完整URL時,這樣做是恰當(dāng)?shù)摹T谶@種情況下,在編輯界面里,文本框?qū)@示圖片的URL。毫無疑問,默認的界面不允許用戶上傳新的圖片,但用戶卻可以修改圖片的URL值。不過,在本教程不會出現(xiàn)這種情況,因為Picture數(shù)據(jù)是直接存儲在數(shù)據(jù)庫的,且DataImageUrlField屬性被設(shè)為CategoryID值。

  為了更好的理解在本教程里編輯某行的ImageField時將會發(fā)生上什么,我們做如下假設(shè):用戶編輯一個CategoryID值為10行,Picture ImageField呈現(xiàn)為一個文本框,顯示10,假設(shè)用戶將其改為50后點Update按鈕,頁面回傳,GridView控件最初產(chǎn)生一個名為CategoryID,值為50的參數(shù)。在GridView傳遞此參數(shù)(連同參數(shù)CategoryName和參數(shù)Description一起)以前,對DataKeys集添加值。因此,將當(dāng)前行的CategoryID值10,覆蓋掉。簡言之,ImageField的編輯界面沒有對本章教程的編輯流程產(chǎn)生任何影響,因為ImageField的DataImageUrlField屬性和DataKey值都是同一個值。

  當(dāng)圖片存儲在數(shù)據(jù)庫時,ImageField將其顯示出來也很容易。不過在編輯界面里我們不需要使用文本框,而提供一個FileUpload控件供最終用戶更改圖片時使用。與BrochurePath不同,我們不允許類的圖片為空——用戶要么提供新圖片要么使用當(dāng)前的圖片。

  為定制ImageField的編輯界面,我們需要將其轉(zhuǎn)化為一個TemplateField。在GridView控件的智能標(biāo)簽里點擊“編輯列”,進入后選中ImageField,再點擊“Convert this field into a TemplateField”鏈接。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖16:將ImageField轉(zhuǎn)換為TemplateField

  轉(zhuǎn)換后的TemplateField由2個模版構(gòu)成。就像下面的聲明代碼顯示的那樣,ItemTemplate模版包含一個Image Web控件,其ImageUrl屬性由一個數(shù)據(jù)綁定語法指定,該數(shù)據(jù)綁定語法基于ImageField的DataImageUrlField和 DataImageUrlFormatString屬性。而EditItemTemplate模版則包含一個TextBox,其Text屬性綁定到DataImageUrlField屬性的值。

?
1
2
3
4
5
6
7
8
9
10
11
<asp:TemplateField>
 <EditItemTemplate>
 <asp:TextBox ID="TextBox1" runat="server"
  Text='<%# Eval("CategoryID") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Image ID="Image1" runat="server"
  ImageUrl='<%# Eval("CategoryID",
  "DisplayCategoryPicture.aspx?CategoryID={0}") %>' />
 </ItemTemplate>
</asp:TemplateField>

  我們需要更新EditItemTemplate模版以包含一個FileUpload控件。從GridView控件的智能標(biāo)簽點“編輯模版”,再在下拉列表選擇Picture TemplateField的EditItemTemplate模版。在模版里你會看見一個TextBox,將其刪除。從工具箱里拖一個FileUpload控件到頁面,設(shè)其ID為PictureUpload。同時在模版里添加如下的文本:“To change the category's picture, specify a new picture. To keep the category's picture the same, leave the field empty”。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖17:在EditItemTemplate模版里添加一個FileUpload控件


完成定制該編輯界面后,在瀏覽器里查看。在只讀模式里,類的圖片和以前沒什么兩樣,當(dāng)點擊Edit按鈕時,picture列將呈現(xiàn)一段文本和一個FileUpload控件。

在ASP.NET 2.0中操作數(shù)據(jù)之五十五:編輯和刪除現(xiàn)有的二進制數(shù)據(jù)
圖18:編輯界面包含一個FileUpload控件

  記得我們設(shè)置ObjectDataSource控件調(diào)用CategoriesBLL的UpdateCategory方法,該方法的一個輸入?yún)?shù)為數(shù)組,用于處理圖片的數(shù)據(jù)。如果該數(shù)組為null值,則調(diào)用另一個重載的UpdateCategory方法,該重載的UpdateCategory方法的UPDATE SQL語句不會更改Picture列,因此類的圖片不會由任何變化。在GridView控件的RowUpdating事件處理器里,我們編程訪問名為PictureUpload的FileUpload控件,判斷是否上傳了文件。如果沒有文件上傳,我們將不會為參數(shù)picture指定值;反之,如果上傳了文件,我們將確保其為JPG格式的文件,并通過參數(shù)picture將其傳給ObjectDataSource控件。

  就像第6步里的代碼一樣,我們此時將要用到的絕大多數(shù)的代碼已經(jīng)存在于DetailsView控件的ItemInserting事件處理器里了。現(xiàn)在我們創(chuàng)建一個新的方法ValidPictureUpload,并更新ItemInserting事件處理器以使用該方法。

  在GridView控件的RowUpdating事件處理器的開頭部分添加如下的代碼,這很重要,因為我們不希望將一個不符合條件的上傳文件存儲在文件系統(tǒng)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Reference the PictureUpload FileUpload
FileUpload PictureUpload =
 (FileUpload)Categories.Rows[e.RowIndex].FindControl("PictureUpload");
if (PictureUpload.HasFile)
{
 // Make sure the picture upload is valid
 if (ValidPictureUpload(PictureUpload))
 {
 e.NewValues["picture"] = PictureUpload.FileBytes;
 }
 else
 {
 // Invalid file upload, cancel update and exit event handler
 e.Cancel = true;
 return;
 }
}

  ValidPictureUpload(FileUpload)方法只有一個FileUpload控件類型的輸入?yún)?shù),通過檢查上傳文件的擴展符以確保上傳的文件為JPG格式。只有當(dāng)上傳了文件時才會調(diào)用該方法;如果沒有文件上傳,參數(shù)picture就只能使用其默認值—null。如果上傳了圖片,且ValidPictureUpload方法返回值true,將用圖片的二進制數(shù)據(jù)對參數(shù)picture賦值。如果ValidPictureUpload方法返回值false,則取消更新,并退出事件處理器。

ValidPictureUpload(FileUpload)方法的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private bool ValidPictureUpload(FileUpload PictureUpload)
{
 // Make sure that a JPG has been uploaded
 if (string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName),
  ".jpg", true) != 0 &&
 string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName),
  ".jpeg", true) != 0)
 {
 UploadWarning.Text =
  "Only JPG documents may be used for a category's picture.";
 UploadWarning.Visible = true;
 return false;
 }
 else
 {
 return true;
 }
}

第8步:將原始幾個類的圖片替換為JPG格式

回想起最開始的那8個類的圖片為位圖文件其包含一個OLE報頭。現(xiàn)在我們添加了新功能以編輯現(xiàn)有記錄的圖片,花幾分鐘將這些位圖文件替換為JPG文件。如果你想使當(dāng)前類的圖片不變,你可以通過下面的布置將其轉(zhuǎn)換為JPG格式:

1.將這些位圖保存在硬盤。在瀏覽器里訪問UpdatingAndDeleting.aspx頁面,對這8個類的圖片,點右鍵,選則保存圖片。

2.在一個圖片編輯器(比如Microsoft Paint)軟件里打開圖片。

3.將圖片保存為JPG格式

4.在編輯界面里,用JPG圖片更新類的picture

完成更新并上傳JPG圖片之后,圖片不會呈現(xiàn)在瀏覽器里,原因是DisplayCategoryPicture.aspx將嘗試對最開始8個類的圖片剝離OLE報頭。怎樣修正呢?我們將剝離OLE報頭的代碼移除。這樣,DisplayCategoryPicture.aspx頁面的Page_Load事件處理器的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected void Page_Load(object sender, EventArgs e)
{
 int categoryID = Convert.ToInt32(Request.QueryString["CategoryID"]);
 
 // Get information about the specified category
 CategoriesBLL categoryAPI = new CategoriesBLL();
 Northwind.CategoriesDataTable categories = _
 categoryAPI.GetCategoryWithBinaryDataByCategoryID(categoryID);
 Northwind.CategoriesRow category = categories[0];
 
 // For new categories, images are JPGs...
 
 // Output HTTP headers providing information about the binary data
 Response.ContentType = "image/jpeg";
 
 // Output the binary data
 Response.BinaryWrite(category.Picture);
}

注意:UpdatingAndDeleting.aspx頁面的編輯和添加界面要稍微復(fù)雜一點。DetailsView和GridView控件里的CategoryName和Description  BoundFields應(yīng)當(dāng)轉(zhuǎn)換成TemplateFields;另外由于CategoryName不能為NULL值,應(yīng)對其添加一個RequiredFieldValidator控件。此外,Description應(yīng)修改為允許換行的的文本框(multi-line TextBox),我將這些留給讀者作為練習(xí)。

總結(jié):
  本篇為處理二進制數(shù)據(jù)的完結(jié)篇,在本章以及前3章我們考察了如何將二進制數(shù)據(jù)存放在文件系統(tǒng)或直接存儲在數(shù)據(jù)庫里。用戶在硬盤里選擇一個文件并將其上傳到服務(wù)器,再存放在文件系統(tǒng)或數(shù)據(jù)庫。ASP.NET 2.0的FileUpload控件提供了上傳的界面。然而,就像在教程《使用FileUpload上傳文件》里提到的那樣,F(xiàn)ileUpload控件控件只適合于上傳小于1MB的文件。我們也探討了如何編輯和刪除當(dāng)前記錄的二進制數(shù)據(jù)。

在接下來的一系列教程里,我們探討各種緩存技術(shù)。使用緩存可以提升應(yīng)用程序的整體性能。

  祝編程快樂!

作者簡介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創(chuàng)始人,自1998年以來一直應(yīng)用 微軟Web技術(shù)。希望對大家的學(xué)習(xí)ASP.NET有所幫助。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 五月婷婷丁香在线 | 国产一区二区精品在线观看 | 亚洲高清视频在线 | 国产精品久久久久久 | 一级一片免费 | 日韩精品一区二区三区在线播放 | 国产在线一区二区三区 | 欧美激情久久久 | 九九热精品在线 | 中文字幕在线精品 | 中文字幕亚洲精品 | 成人欧美一区二区三区色青冈 | 亚洲a网 | 国产精品女同一区二区久久夜 | 精品国产不卡一区二区三区 | 日韩av在线一区 | 天天射影院| 久久久久久国产 | 久久精品亚洲精品 | 成人久久久精品国产乱码一区二区 | 一区二区三区精品视频 | 18.wxww.成人性视频高清 | 日韩一区二区三区在线观看 | 国产亚洲视频在线观看 | 在线永久免费观看日韩a | 午夜国产 | 国产精品视频入口 | 国产中文字幕在线看 | 亚洲 中文 欧美 日韩 在线观看 | 国产精品久久久久久久9999 | 日本久久精品视频 | 亚洲国产一级毛片 | 黄瓜av在线 | 国产伦精品一区二区三区 | 国产精品污www在线观看 | 欧美精品黄色 | 国产在线观看 | 毛片一区 | 日韩一区二区三区视频 | 国产片一区二区三区 | 91在线视频 |