




已阅读5页,还剩24页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
在ASP.NET 2.0中操作数据之五十五:编辑和删除现有的二进制数据作者:heker2007 字体:增加减小 类型:转载 时间:2016-05-17我要评论前面几节我们讲解了ASP.NET中如何上传显示二进制图片数据,这一节我们来介绍一下如何在GridView编辑和删除已经存在的二进制数据。导言:在前面的3章里我们为处理二进制数据添加了很多的功能。我们首先在表Categories里添加BrochurePath列,并更新了体系结构。同样,为了处理表Categorie里现有的Picture列,我们在数据访问层和业务逻辑层里增加了相应的方法。同时我们创建一个页面,在GridView控件里显示二进制数据包含一个指向说明小册子的下载链接,并将每个类的图片显示在元素里。同时我们添加一个DetailsView控件,供用户添加新的类,并上传其图片和小册子数据。剩下的就是添加编辑和删除功能,本章我们将通过GridView控件内建的编辑和删除功能来实现。当编辑一个类时,我们允许用户用任意指定的图片将原来的换掉;也可以用新的小册子将现有的替换掉,甚至不再包含小册子文件。让我们开始吧!第1步:更新数据访问层虽然数据访问层包含自动生成的Insert, Update和Delete方法,但它们都基于CategoriesTableAdapter的主查询,因此并不包含Picture列。自然,Insert和Update方法也不包含picture列的相应参数。就像56章做的那样,我们需要为更新Categories表而创建新的TableAdapter方法。右键点击CategoriesTableAdapter的顶部,选择“添加查询”,打开TableAdapter查询设置向导,我们首先选择“使用SQL语句”,点Next,再选“UPDATE”,再点Next.图1:选择“UPDATE”选项我们现在需要指定UPDATE SQL语句。向导自动创建一个基于TableAdapter主查询的UPDATE语句(它更新CategoryName, Description和BrochurePath值)。更新该语句以包含Picture列,以及Picture参数,像如下这样:?123456UPDATE Categories SETCategoryName = CategoryName,Description = Description,BrochurePath = BrochurePath ,Picture = PictureWHERE (CategoryID = Original_CategoryID)最后,向导要求我们为新的TableAdapter方法命名,我们取为UpdateWithPicture,再点Finish。图2:为新方法命名为UpdateWithPicture第2步:添加新的业务逻辑方法除了更新DAL外,我们需要更新BLL以包含更新、删除类的方法。以下是表现层需要调用的方法:为了删除一个类,我们使用CategoriesTableAdapter的自动生成的Delete方法,在类CategoriesBLL里添加如下的方法:?123456789System.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 falsereturn rowsAffected = 1;本教程,为了更新一个类,我们将创建2个方法。一个方法接受picture值,并调用我们刚刚添加到CategoriesTableAdapter里的UpdateWithPicture方法。另一个方法只接受CategoryName, Description和BrochurePath值, 并调用CategoriesTableAdapter类里自动生成的Update语句。为什么要使用2种方法呢?某些情况下,用户更新类时同时更新其图片,这时就需要上传一张新图片。上传图片的数据将在UPDATE语句里用到;另一种情况,用户只想更新类的name和description信息,因此我们需要使用2种更新方法。业务逻辑层会根据是否传入picture值来判断使用哪种方法。为达该目的,我们要在CategoriesBLL类里添加2个方法,名字都是UpdateCategory,第一个方法接受的参数包括3个string,1个byte数组和1个int;第二个方法接受的参数包括3个string和1个int。3个字符串参数代表类的name, description和brochure文件路径,byte数组包含的是类的picture数据,int代表类记录的CategoryID,我们注意到,当传入的byte数组为null时,第一个方法将调用第二个方法。?12345678910111213141516171819202122232425262728System.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 overloadif (picture = null)return UpdateCategory(categoryName, description, brochurePath, categoryID);/ Update picture, as wellint rowsAffected = Adapter.UpdateWithPicture(categoryName, description, brochurePath, picture, categoryID);/ Return true if precisely one row was updated, otherwise falsereturn 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 falsereturn rowsAffected = 1;第3步:拷贝功能在上一章里,我们创建了一个UploadInDetailsView.aspx页面,在一个GridView控件列出所有的类,再通过一个DetailsView控件来添加新的类。在本教程,我们将扩展GridView控件以支持编辑和删除功能。不过我们不再使用UploadInDetailsView.aspx页面,让我们在/BinaryData文件夹里创建一个新页面,UpdatingAndDeleting.aspx,将UploadInDetailsView.aspx页面的声明代码复制并粘贴到页面UpdatingAndDeleting.aspx.打开UploadInDetailsView.aspx页面,将其元素里的声明代码复制下来,就像图3那样。接下来,打开UpdatingAndDeleting.aspx页面,把代码粘贴在元素里。同样的,将UploadInDetailsView.aspx页面的后台代码拷贝到UpdatingAndDeleting.aspx。图3:将UploadInDetailsView.aspx页面的声明代码拷贝下来完成后,登录UpdatingAndDeleting.aspx页面,你将会看到相同的输出效果。感觉用起来和UploadInDetailsView.aspx页面一样。第4步:添加ObjectDataSource和GridView的删除功能就像在教程16概述插入、更新和删除数据里探讨的一样,只要GridView控件绑定的数据源支持“删除”功能,我们就可以为GridView控件启用删除功能。不过,GridView控件绑定的ObjectDataSource(也就是CategoriesDataSource)目前并不支持删除。为支持删除,在ObjectDataSource的智能标签里点“配置数据源”,一直点到“定义数据方法”界面。虽然当前只指定了ObjectDataSource控件InsertMethod属性和SelectMethod属性,但向导自动地分别为UPDATE标签和DELETE标签指定UpdateCategory方法和DeleteCategory方法。为什么呢?因为我们在CategoriesBLL类里为上述2种方法使用了DataObjectMethodAttribute属性,作用是分别使其成为默认的“更新”和“删除”方法。不过现在我们在UPDATE标签的下拉列表里选“(None)”, 而 DELETE标签里仍然为DeleteCategory方法。我们将在第6步添加更新功能。图4:设置ObjectDataSource控件使用DeleteCategory方法注意:完成设置后,Visual Studio会问你是否“刷新列和主键”,选择No,因为选择Yes将会把我们自己定制的任何列覆盖掉。现在,ObjectDataSource控件将包含DeleteMethod属性和对应的DeleteParameter参数。我们记得在以前的教程提到过,当使用向导指定方法时,Visual Studio会自动的将ObjectDataSource控件的OldValuesParameterFormatString属性设置为original_0,这将导致更新和删除时出现问题。为此,要么将清除该属性,要么将其设置为默认的0值。对该属性的更详细讨论见教程16概述插入、更新和删除数据完成后,ObjectDataSource控件的声明代码看起来应该像下面的一样:?1234567891011121314设置完ObjectDataSource后,就可以启用GridView的删除功能了,方法是点击其智能标签里的“删除选项”。这将使GridView增加一个CommandField,其ShowDeleteButton属性为true。图5:启用GridView控件的删除功能花几分钟测试删除功能。由于表Products和表Categories之间有一个外键CategoryID,当你删除现有的8个类中的任何一个时,你会得到一个外键约束冲突异常。为顺利的实现测试,我们需要添加一个附带图片和说明小册子的新类,如图6所示,小册子为Test.pdf,图7为添加了测试类的GridView控件界面。图6:添加一个附带Brochure和Image文件的测试类图7:添加测试类后,显示在GridView控件里在Visual Studio里刷新解决资源管理器,你会在文件夹/Brochures里看到Test.pdf文件(见图8)下一步,点击Test类的Delete链接,页面回传,引发CategoriesBLL的DeleteCategory 方法,该方法又调用DAL层的Delete方法,向数据库发送适当的DELETE命令。最后数据重新绑定到GridView控件,Test类将不再显示出来。虽然已经成功地将Test类从Categories表删除,但存储在文件系统的对应小册子仍旧存在,刷新解决资源管理器,你将发现Test.pdf依然放在/Brochures文件夹里。图8:Test.pdf文件并没有从文件系统删除第5步:删除残存的Brochure文件未将二进制数据存储进数据库时面临的一个问题便是:当删除一条数据库记录时,我们需要另外采取步骤来删除该记录对应的二进制数据文件。当执行delete命令时,会发生一些事前事件和事后事件(pre- and post-action events),我们需要创建对应的事件处理器。在Categories表的记录被删除之前,我们需要确定对应PDF文件的路径,但在删除记录之前我们不会删除其对应的PDF文件,以防发生异常或记录最终未被删除的情况。从事件发生的时间先后顺序来看,GridView控件的RowDeleting事件在调用ObjectDataSource控件的delete命令前发生;而RowDeleted事件在调用ObjectDataSource控件的delete命令之后再发生。创建这2个事件处理器,代码如下:?12345678910111213141516171819202122232425262728293031/ A page variable to remember the deleted categorys BrochurePath valuestring deletedCategorysPdfPath = null;protected void Categories_RowDeleting(object sender, GridViewDeleteEventArgs e)/ Determine the PDF path for the category being categoryID = Convert.ToInt32(e.KeysCategoryID);CategoriesBLL categoryAPI = new CategoriesBLL();Northwind.CategoriesDataTable categories =categoryAPI.GetCategoryByCategoryID(categoryID);Northwind.CategoriesRow category = categories0;if (category.IsBrochurePathNull()deletedCategorysPdfPath = null;elsedeletedCategorysPdfPath = category.BrochurePath;protected void Categories_RowDeleted(object sender, GridViewDeletedEventArgs e)/ Delete the brochure file if there were no problems deleting the recordif (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集合。接着,调用类CategoriesBLL的GetCategoryByCategoryID(categoryID)方法来返回被删记录的信息,若返回的BrochurePath值不为NULL,那么将其赋值给页面参数deletedCategorysPdfPath,再在RowDeleted事件处理器里删除文件。注意:在RowDeleting事件处理器里,我们没有返回被删记录的BrochurePath信息,而是将BrochurePath添加到GridView的DataKeyNames属性,再通过访问e.Keys来获取该记录的值。这样做虽然稍微增大了GridView的视图状态,但减少了必要的代码,也省了一步访问数据库。调用ObjectDataSource控件的delete命令后,紧接着发生GridView控件的RowDeleted事件,如果删除过程没有异常且deletedCategorysPdfPath值不为空,那就将对应的PDF文件从文件系统删除。我们注意到,代码没有删除类的picture,那是因为picture数据是直接存储在数据库里的,当删除记录时就一起删除了。添加完上述2个事件处理器后,再次测试删除。当删除某个类时,其对应的PDF文件也删除了。下面我们深入研究添加更新功能以应对类的brochure和picture.第6步探讨更新brochure信息的技术,第7章探讨更新picture。第6步:更新类的Brochure就像在教程16概述插入、更新和删除数据里探讨的一样,如果GridView的数据源控件支持编辑,那么我们就可以启用GridView控件的编辑功能。当前,名为CategoriesDataSource的ObjectDataSource控件并不支持编辑,那让我们添加吧。点击ObjectDataSource控件的“设置数据源”链接,一直点到“定义数据方法”界面。由于在CategoriesBLL里对重载的UpdateCategory方法使用了DataObjectMethodAttribute属性,UPDATE标签的下拉列表自动的选择了该方法,它包含4个输入参数(不包含Picture)。我们选择另一个包含5个输入参数的重载的UpdateCategory方法。图9:设置ObjectDataSource控件使用包含Picture参数的UpdateCategory方法ObjectDataSource控件现在包含了UpdateMethod属性以及相应的UpdateParameters参数集。就像在第4步提到的一样,当使用设置向导时,Visual Studio会将ObjectDataSource控件的OldValuesParameterFormatString属性设置为original_0,这导致调用update和delete方法时出现问题。因此,要么将该属性清除,要么设该属性为0。完成后,ObjectDataSource控件的声明代码看起来应该和下面的差不多:?123456789101112131415161718192021要启用编辑功能,从GridView控件的智能标签里选“编辑”。这将设置CommandField的ShowEditButton属性为true,结果是为每行添加一个Edit按钮(当记录处于编辑状态时,将呈现为Update和Cancel按钮)图10:启用GridView控件的编辑功能从浏览器查看该页面,点某条记录的Edit按钮。CategoryName和Description列呈现为一个文本框。由于BrochurePath TemplateField没有EditItemTemplate模板,所以它依旧呈现其ItemTemplate模板一个指向brochure的链接。Picture列呈现为一个文本框,并且该Picture ImageField的Text属性被指派为DataImageUrlField值,在这里,即CategoryID.图11:BrochurePath列没有编辑界面定制BrochurePath编辑界面我们可以为BrochurePath TemplateField创建一个编辑界面,我们可以选择:.维持原样.上传新的brochure以作更新.将brochure删除(这样一来,类就没有对应的brochure了)我们也应该更新Picture ImageField的编辑界面,不过我们将放在第7步来讨论。在GridView控件的智能标签里选择“编辑模板”,再从下拉列表里选BrochurePath TemplateField的EditItemTemplate模板。在模板里添加一个RadioButtonList Web控件,其ID为BrochureOptions;AutoPostBack属性为true.再在属性窗口里点Items属性的椭圆型区域,进入ListItem Collection Editor界面,分别添加值为1,2,3的选项:.Use current brochure.Remove current brochure.Upload new brochure设第一个ListItem的Selected属性为true.图12:为RadioButtonList控件添加3个ListItems在RadioButtonList控件下面,添加一个FileUpload控件,ID为BrochureUpload,设其Visible属性为false。图13:在EditItemTemplate模板里添加RadioButtonList和FileUpload控件RadioButtonList控件为用户提供了3个选择,只有当选择“Upload new brochure”时, FileUpload控件才会展现出来。为此,我们为RadioButtonList控件的SelectedIndexChanged事件创建事件处理器,如下:?1234567891011121314protected void BrochureOptions_SelectedIndexChanged(object sender, EventArgs e)/ Get a reference to the RadioButtonList and its ParentRadioButtonList BrochureOptions = (RadioButtonList)sender;Control parent = BrochureOptions.Parent;/ Now use FindControl(controlID) to get a reference of the/ FileUpload controlFileUpload BrochureUpload =(FileUpload)parent.FindControl(BrochureUpload);/ Only show BrochureUpload if SelectedValue = 3BrochureUpload.Visible = (BrochureOptions.SelectedValue = 3);由于RadioButtonList控件和FileUpload控件同时出现在一个模板里,我们需要通过编程来访问这2个控件。在SelectedIndexChanged事件处理器里,我们通过输入参数sender来引用RadioButtonList控件。为了获取FileUpload控件,我们需要使用RadioButtonList的父控件(parent control),并使用FindControl(controlID)方法。一旦我们同时获取了RadioButtonList和FileUpload控件时,只要RadioButtonList控件的SelectedValue值等于3,即“Upload new brochure” ListItem的值时,将FileUpload控件的Visible属性设置为true 。添加完上述代码后,花几分钟时间来测试编辑页面。点击某行的Edit按钮,默认是选中“Use current brochure”项,改选另一项,页面产生回传,如果是选择第3项,则FileUpload控件将会显示出来,否则处于隐身状态。图14显示点击Edit按钮的情形,而图15则是选择“Upload new brochure”时的情形。图14:默认选择“Use current brochure”项图15:选择“Upload new brochure”时FileUpload控件显示出来保存Brochure文件并更新BrochurePath列当点击GridView控件的Update按钮时,触发RowUpdating事件,调用ObjectDataSource控件的update命令,然后触发GridView控件的RowUpdated事件。跟deleting流程类似,我们需要创建这些事件的处理器。在RowUpdating事件处理器里,我们需要根据RadioButtonList的SelectedValue值来判断下一步怎么做。.如果SelectedValue值为1,我们将保持rochurePath不变。所以我们将ObjectDataSource控件的brochurePath参数设置为当前处于编辑状态记录的BrochurePath值,方法为e.NewValuesbrochurePath = value.如果SelectedValue值为2,意味着将BrochurePath设为NULL。为此,我们需要将ObjectDataSource控件的brochurePath参数设为Nothing,结果就是在UPDATE命令里使用NULL。如果存在对应的brochure文件,我们必须将其删除,前提是没有抛出任何的异常。.如果SelectedValue值为3,我们必须确保用户已经上传了一个PDF文件并将其保存在文件系统,然后更新记录的BrochurePath值。我们要先将被替换的前一个文件删除掉,当然前提是没有引发异常。在上一章里,当在DetailsView控件里添加新记录时,触发DetailsView控件的ItemInserting事件。在本章,当RadioButtonList控件的SelectedValue为3时(即我们选择Upload new brochure时),接下来要采取的步骤实际上与DetailsView控件的ItemInserting事件处理器实现的功能相似。根据实现的功能,我划分为2个方法:.ProcessBrochureUpload(FileUpload, out bool):它以一个FileUpload控件实例为输入参数,结果为一个布尔值(Boolean)。根据该布尔值判断是否继续更新或删除操作,抑或取消操作。如果存在上传文件该方法就返回其路径,反之返回null。.DeleteRememberedBrochurePath:如果页面变量deletedCategorysPdfPath不为null,则删除该参数指定的文件。下面是上述2种方法的代码。注意ProcessBrochureUpload方法和DetailsView控件的ItemInserting事件处理器有某些相似性,在本章,我们更新DetailsView控件的事件处理器以使用这些新方法。下载本章的代码,查看我们对DetailsView控件的事件处理器所做的修改。?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051private string ProcessBrochureUpload(FileUpload BrochureUpload, out bool CancelOperation)CancelOperation = false; / by default, do not cancel operationif (BrochureUpload.HasFile)/ Make sure that a PDF has been uploadedif (string.Compare(System.IO.Path.GetExtension(BrochureUpload.FileName),.pdf, true) != 0)UploadWarning.Text =Only PDF documents may be used for a categorys 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 parameterBrochureUpload.SaveAs(Server.MapPath(brochurePath);return brochurePath;else/ No file uploadedreturn null;private void DeleteRememberedBrochurePath()/ Is there a file to delete?if (deletedCategorysPdfPath != null)System.IO.File.Delete(Server.MapPath(deletedCategorysPdfPath);在GridView控件的RowUpdating和RowUpdated事件处理器里使用上面2个方法,如下:?1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768protected void Categories_RowUpdating(object sender, GridViewUpdateEventArgs e)/ Reference the RadioButtonListRadioButtonList BrochureOptions =(RadioButtonList)Categories.Rowse.RowIndex.FindControl(BrochureOptions);/ Get BrochurePath information about the record being updatedint categoryID = Convert.ToInt32(e.KeysCategoryID);CategoriesBLL categoryAPI = new CategoriesBLL();Northwind.CategoriesDataTable categories =categoryAPI.GetCategoryByCategoryID(categoryID);Northwind.CategoriesRow category = categories0;if (BrochureOptions.SelectedValue = 1)/ Use current value for BrochurePathif (category.IsBrochurePathNull()e.NewValuesbrochurePath = null;elsee.NewValuesbrochurePath = category.BrochurePath;else if (BrochureOptions.SelectedValue = 2)/ Remove the current brochure (set it to NULL in the database)e.NewValuesbrochurePath = null;else if (BrochureOptions.SelectedValue = 3)/ Reference the BrochurePath FileUpload controlFileUpload BrochureUpload =(FileUpload)Categories.Rowse.RowIndex.FindControl(BrochureUpload);/ Process the BrochureUploadbool cancelOperation = false;e.NewValuesbrochurePath =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 fileif (category.IsBrochurePathNull()deletedCategorysPdfPath = null;elsedeletedCategorysPdfPath = 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 oneif (e.Exception = null)DeleteRememberedBrochurePath();注意:RowUpdating事件处理器是如何根据SelectedValue值的不同而使用一系列的条件语句来实现相应的功能。使用上面的代码,我们就可以编辑一个类了,使用其当前的brochure,或不使用brochure,再或者使用一个新的brochure。在RowUpdating和RowUpdated事件处理器里设置断点(breakpoints)吧,以便更好的理解处理流程。第7步:上传新图片Pic
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 绿化迁改申请报告(3篇)
- 区域玩具销售合同(标准版)
- 留学护照申请报告模板(3篇)
- 商铺返租合同(标准版)
- 丽的字草书课件
- 公司合同法实务培训课件
- Dexamethasone-9-11-epoxide-Standard-生命科学试剂-MCE
- 公司厨房安全培训内容课件
- 临西市网络安全培训课件
- 临终关怀课件
- GB/T 7713.4-2025信息与文献编写规则第4部分:数据论文
- 2025年全国通信专业技术人员职业水平考试(通信专业实务终端与业务)(高、中级)练习题及答案
- 土地出让课件
- 2025-2026学年第一学期学校教导处工作计划:扎根常规提质效稳中求进促提升
- 主体结构劳务分包工程(八标段)施工组织设计
- 2025年移动初级解决方案经理认证理论考试指导题库-下(多选、判断题)
- 营养与慢性伤口愈合的关系
- (正式版)JBT 9229-2024 剪叉式升降工作平台
- Q∕GDW 11445-2015 国家电网公司管理信息系统安全基线要求
- 财务报销流程培训PPT模板课件
- DG∕T 154-2022 热风炉
评论
0/150
提交评论