Data Tutorial 66 VB
Data Tutorial 66 VB
NETintheWorkingwithData
inASP.NET2.0sectionoftheASP.NETsiteathttp://www.asp.net/learn/dataaccess/default.aspx.
WorkingwithDatainASP.NET2.0::BatchInserting
Introduction
Inthe BatchUpdatingtutorialwelookedatcustomizingtheGridViewcontroltopresentaninterfacewhere
multiplerecordswereeditable.Theuservisitingthepagecouldmakeaseriesofchangesandthen,withasingle
buttonclick,performabatchupdate.Forsituationswhereuserscommonlyupdatemanyrecordsinonego,suchan
interfacecansavecountlessclicksandkeyboardtomousecontextswitcheswhencomparedtothedefaultperrow
editingfeaturesthatwerefirstexploredbackinthe AnOverviewofInserting,Updating,andDeletingData
tutorial.
Thisconceptcanalsobeappliedwhenaddingrecords.ImaginethathereatNorthwindTraderswecommonly
receiveshipmentsfromsuppliersthatcontainanumberofproductsforaparticularcategory.Asanexample,we
mightreceiveashipmentofsixdifferentteaandcoffeeproductsfromTokyoTraders.Ifauserentersthesix
productsoneatatimethroughaDetailsViewcontrol,theywillhavetochoosemanyofthesamevaluesoverand
overagain:theywillneedtochoosethesamecategory(Beverages),thesamesupplier(TokyoTraders),thesame
discontinuedvalue(False),andthesameunitsonordervalue(0).Thisrepetitivedataentryisnotonlytime
consuming,butispronetoerrors.
Withalittleworkwecancreateabatchinsertinginterfacethatenablestheusertochoosethesupplierandcategory
once,enteraseriesofproductnamesandunitprices,andthenclickabuttontoaddthenewproductstothe
database(seeFigure1).Aseachproductisadded,its ProductName andUnitPrice datafieldsareassignedthe
valuesenteredintheTextBoxes,whileitsCategoryID andSupplierID valuesareassignedthevaluesfromthe
DropDownListsatthetopfotheform.TheDiscontinued andUnitsOnOrder valuesaresettothehardcoded
valuesofFalse and0,respectively.
Figure1:TheBatchInsertingInterface
1 of20
InthistutorialwewillcreateapagethatimplementsthebatchinsertinginterfaceshowninFigure1.Aswiththe
previoustwotutorials,wewillwraptheinsertionswithinthescopeofatransactiontoensureatomicity.Letsget
started!
Step1:CreatingtheDisplayInterface
Thistutorialwillconsistofasinglepagethatisdividedintotworegions:adisplayregionandaninsertingregion.
Thedisplayinterface,whichwellcreateinthisstep,showstheproductsinaGridViewandincludesabuttontitled
ProcessProductShipment. Whenthisbuttonisclicked,thedisplayinterfaceisreplacedwiththeinserting
interface,whichisshowninFigure1.Thedisplayinterfacereturnsafterthe AddProductsfromShipmentor
Cancel buttonsareclicked.WellcreatetheinsertinginterfaceinStep2.
Whencreatingapagethathastwointerfaces,onlyoneofwhichisvisibleatatime,eachinterfacetypicallyis
placedwithinaPanelWebcontrol,whichservesasacontainerforothercontrols.Therefore,ourpagewillhave
twoPanelcontrolsoneforeachinterface.
StartbyopeningtheBatchInsert.aspx pageintheBatchData folderanddragaPanelfromtheToolboxontothe
Designer(seeFigure2).SetthePanelsID propertytoDisplayInterface.WhenaddingthePaneltothe
Designer,itsHeight andWidth propertiesaresetto50pxand125px,respectively.Clearoutthesepropertyvalues
fromthePropertieswindow.
Figure2:DragaPanelfromtheToolboxontotheDesigner
ConfigureDataSourcewizard.
3 of20
Figure4:SettheDropDownListsintheUPDATE,INSERT,andDELETETabsto(None)
AftercompletingtheObjectDataSourcewizard,VisualStudiowilladdBoundFieldsandaCheckBoxFieldforthe
productdatafields.RemoveallbuttheProductName,CategoryName,SupplierName,UnitPrice,and
Discontinued fields.Feelfreetomakeanyaestheticcustomizations.IdecidedtoformattheUnitPrice fieldasa
currencyvalue,reorderedthefields,andrenamedseveralofthefieldsHeaderText values.Alsoconfigurethe
GridViewtoincludepagingandsortingsupportbycheckingtheEnablePagingandEnableSorting
checkboxesintheGridViewssmarttag.
AfteraddingthePanel,Button,GridView,andObjectDataSourcecontrolsandcustomizingtheGridViewsfields,
yourpagesdeclarativemarkupshouldlooksimilartothefollowing:
<asp:PanelID="DisplayInterface"runat="server">
<p>
<asp:ButtonID="ProcessShipment"runat="server"
Text="ProcessProductShipment"/>
</p>
<asp:GridViewID="ProductsGrid"runat="server"AllowPaging="True"
AllowSorting="True"AutoGenerateColumns="False"
DataKeyNames="ProductID"DataSourceID="ProductsDataSource">
<Columns>
<asp:BoundFieldDataField="ProductName"HeaderText="Product"
SortExpression="ProductName"/>
<asp:BoundFieldDataField="CategoryName"HeaderText="Category"
ReadOnly="True"SortExpression="CategoryName"/>
<asp:BoundFieldDataField="SupplierName"HeaderText="Supplier"
ReadOnly="True"SortExpression="SupplierName"/>
4 of20
<asp:BoundFieldDataField="UnitPrice"DataFormatString="{0:c}"
HeaderText="Price"HtmlEncode="False"
SortExpression="UnitPrice">
<ItemStyleHorizontalAlign="Right"/>
</asp:BoundField>
<asp:CheckBoxFieldDataField="Discontinued"HeaderText="Discontinued"
SortExpression="Discontinued">
<ItemStyleHorizontalAlign="Center"/>
</asp:CheckBoxField>
</Columns>
</asp:GridView>
<asp:ObjectDataSourceID="ProductsDataSource"runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts"TypeName="ProductsBLL">
</asp:ObjectDataSource>
</asp:Panel>
NotethatthemarkupfortheButtonandGridViewappearwithintheopeningandclosing<asp:Panel> tags.Since
thesecontrolsarewithintheDisplayInterface Panel,wecanhidethembysimplysettingthePanelsVisible
propertytoFalse.Step3looksatprogrammaticallychangingthePanelsVisible propertyinresponsetoabutton
clicktoshowoneinterfacewhilehidingtheother.
Takeamomenttoviewourprogressthroughabrowser.AsFigure5shows,youshouldseeaProcessProduct
ShipmentbuttonaboveaGridViewthatliststheproductstenatatime.
Figure5:TheGridViewListstheProductsandOffersSortingandPagingCapabilities
5 of20
Step2:CreatingtheInsertingInterface
Withthedisplayinterfacecomplete,werereadytocreatetheinsertinginterface.Forthistutorial,letscreatean
insertinginterfacethatpromptsforasinglesupplierandcategoryvalueandthenallowstheusertoenteruptofive
productnamesandunitpricevalues.Withthisinterface,theusercanaddonetofivenewproductsthatallsharethe
samecategoryandsupplier,buthaveuniqueproductnamesandprices.
StartbydraggingaPanelfromtheToolboxontotheDesigner,placingitbeneaththeexistingDisplayInterface
Panel.SettheID propertyofthisnewlyaddedPaneltoInsertingInterface andsetitsVisible propertyto
False.WelladdcodethatsetstheInsertingInterface PanelsVisible propertytoTrue inStep3.Alsoclear
outthePanelsHeight andWidth propertyvalues.
Next,weneedtocreatetheinsertinginterfacethatwasshownbackinFigure1.Thisinterfacecanbecreated
throughavarietyofHTMLtechniques,butwewilluseafairlystraightforwardone:afourcolumn,sevenrow
table.
Note:WhenenteringmarkupforHTML<table> elements,IprefertousetheSourceview.WhileVisual
Studiodoeshavetoolsforadding <table> elementsthroughtheDesigner,theDesignerseemsalltoowilling
toinjectunaskedforstyle settingsintothemarkup.OnceIhavecreatedthe<table> markup,Iusually
returntotheDesignertoaddtheWebcontrolsandsettheirproperties.Whencreatingtableswithpre
determinedcolumnsandrowsIpreferusingstaticHTMLratherthantheTableWebcontrol becauseany
WebcontrolsplacedwithinaTableWebcontrolcanonlybeaccessedusingtheFindControl
("controlID") pattern.Ido,however,useTableWebcontrolsfordynamicallysizedtables(oneswhose
rowsorcolumnsarebasedonsomedatabaseoruserspecifiedcriteria),sincetheTableWebcontrolcanbe
constructedprogrammatically.
Enterthefollowingmarkupwithinthe<asp:Panel> tagsoftheInsertingInterface Panel:
<tableclass="DataWebControlStyle"cellspacing="0">
<trclass="BatchInsertHeaderRow">
<tdclass="BatchInsertLabel">Supplier:</td>
<td></td>
<tdclass="BatchInsertLabel">Category:</td>
<td></td>
</tr>
<trclass="BatchInsertRow">
<tdclass="BatchInsertLabel">Product:</td>
<td></td>
<tdclass="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<trclass="BatchInsertAlternatingRow">
<tdclass="BatchInsertLabel">Product:</td>
<td></td>
<tdclass="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<trclass="BatchInsertRow">
<tdclass="BatchInsertLabel">Product:</td>
<td></td>
<tdclass="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<trclass="BatchInsertAlternatingRow">
6 of20
<tdclass="BatchInsertLabel">Product:</td>
<td></td>
<tdclass="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<trclass="BatchInsertRow">
<tdclass="BatchInsertLabel">Product:</td>
<td></td>
<tdclass="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<trclass="BatchInsertFooterRow">
<tdcolspan="4">
</td>
</tr>
</table>
This<table> markupdoesnotincludeanyWebcontrolsyet,welladdthosemomentarily.Notethateach<tr>
elementcontainsaparticularCSSclasssetting:BatchInsertHeaderRow fortheheaderrowwherethesupplier
andcategoryDropDownListswillgoBatchInsertFooterRow forthefooterrowwheretheAddProductsfrom
ShipmentandCancelButtonswillgoandalternatingBatchInsertRow andBatchInsertAlternatingRow
valuesfortherowsthatwillcontaintheproductandunitpriceTextBoxcontrols.IvecreatedcorrespondingCSS
classesintheStyles.css filetogivetheinsertinginterfaceanappearancesimilartotheGridViewand
DetailsViewcontrolsweveusedthroughoutthesetutorials.TheseCSSclassesareshownbelow.
/***Stylesfor~/BatchData/BatchInsert.aspxtutorial***/
.BatchInsertLabel
{
fontweight:bold
textalign:right
}
.BatchInsertHeaderRowtd
{
color:White
backgroundcolor:#900
padding:11px
}
.BatchInsertFooterRowtd
{
textalign:center
paddingtop:5px
}
.BatchInsertRow
{
}
.BatchInsertAlternatingRow
{
backgroundcolor:#fcc
}
Withthismarkupentered,returntotheDesignview.This<table> shouldshowasafourcolumn,sevenrowtable
intheDesigner,asFigure6illustrates.
7 of20
Figure6:TheInsertingInterfaceisComposedofaFourColumn,SevenRowTable
WerenowreadytoaddtheWebcontrolstotheinsertinginterface.DragtwoDropDownListsfromtheToolbox
intotheappropriatecellsinthetable oneforthesupplierandoneforthecategory.
SetthesupplierDropDownListsID propertytoSuppliers andbindittoanewObjectDataSourcenamed
SuppliersDataSource.ConfigurethenewObjectDataSourcetoretrieveitsdatafromtheSuppliersBLL classs
GetSuppliers methodandsettheUPDATEtabsdropdownlistto(None). ClickFinishtocompletethe
wizard.
8 of20
9 of20
NamethesecondDropDownListCategories andbindittoanewObjectDataSourcenamed
CategoriesDataSource.ConfiguretheCategoriesDataSource ObjectDataSourcetousetheCategoriesBLL
classsGetCategories methodsetthedropdownlistsintheUPDATEandDELETEtabsto(None)andclick
Finishtocompletethewizard.Finally,havetheDropDownListdisplaytheCategoryName datafieldandusethe
CategoryID asthevalue.
AfterthesetwoDropDownListshavebeenaddedandboundtoappropriatelyconfiguredObjectDataSources,your
screenshouldlooksimilartoFigure9.
10 of20
WenowneedtocreatetheTextBoxestocollectthenameandpriceforeachnewproduct.DragaTextBoxcontrol
fromtheToolboxontotheDesignerforeachofthefiveproductnameandpricerows.SettheID propertiesofthe
TextBoxestoProductName1,UnitPrice1,ProductName2,UnitPrice2,ProductName3,UnitPrice3,andsoon.
AddaCompareValidatoraftereachoftheunitpriceTextBoxes,settingtheControlToValidate propertytothe
appropriateID.AlsosettheOperator propertytoGreaterThanEqual,ValueToCompare to0, andType to
Currency.ThesesettingsinstructtheCompareValidatortoensurethattheprice,ifentered,isavalidcurrency
valuethatisgreaterthanorequaltozero.SettheText propertyto*, andErrorMessage toThepricemustbe
greaterthanorequaltozero.Also,pleaseomitanycurrencysymbols.
Note:TheinsertinginterfacedoesnotincludeanyRequiredFieldValidatorcontrols,eventhoughthe
ProductName fieldinthe Products databasetabledoesnotallowNULL values.Thisisbecausewewantto
lettheuserenteruptofiveproducts.Forexample,iftheuserweretoprovidetheproductnameandunit
priceforthefirstthreerows,leavingthelasttworowsblank,wedjustaddthreenewproductstothesystem.
SinceProductName isrequired,however,wewillneedtoprogrammaticallychecktoensurethatifaunit
priceisenteredthatacorrespondingproductnamevalueisprovided.WelltacklethischeckinStep4.
Whenvalidatingtheusersinput,theCompareValidatorreportsinvaliddataifthevaluecontainsacurrency
symbol.Adda$infrontofeachoftheunitpriceTextBoxestoserveasavisualcuethatinstructstheuserto
omitthecurrencysymbolwhenenteringtheprice.
Lastly,addaValidationSummarycontrolwithintheInsertingInterface Panel,settingsitsShowMessageBox
propertytoTrue anditsShowSummary propertytoFalse.Withthesesettings,iftheuserentersaninvalidunitprice
value,anasteriskwillappearnexttotheoffendingTextBoxcontrolsandtheValidationSummarywilldisplaya
clientsidemessageboxthatshowstheerrormessagewespecifiedearlier.
Atthispoint,yourscreenshouldlooksimilartoFigure10.
11 of20
Figure10:TheInsertingInterfaceNowIncludesTextBoxesfortheProducts NamesandPrices
NextweneedtoaddtheAddProductsfromShipment andCancelbuttonstothefooterrow.Dragtwo
ButtoncontrolsfromtheToolboxintothefooteroftheinsertinginterface,settingtheButtonsID propertiesto
AddProducts andCancelButton andText propertiestoAddProductsfromShipment andCancel,
respectively.Inaddition,settheCancelButton controlsCausesValidation propertytofalse.
Finally,weneedtoaddaLabelWebcontrolthatwilldisplaystatusmessagesforthetwointerfaces.Forexample,
whenausersuccessfullyaddsanewshipmentofproducts,wewanttoreturntothedisplayinterfaceanddisplaya
confirmationmessage.If,however,theuserprovidesapriceforanewproductbutleavesofftheproductname,we
needtodisplayawarningmessagesincetheProductName fieldisrequired.Sinceweneedthismessagetodisplay
forbothinterfaces,placeitatthetopofthepageoutsideofthePanels.
DragaLabelWebcontrolfromtheToolboxtothetopofthepageintheDesigner.SettheID propertyto
StatusLabel,clearouttheText property,andsetthe Visible andEnableViewState propertiesto False.Aswe
haveseeninprevioustutorials,settingtheEnableViewState propertytoFalse allowsustoprogrammatically
changetheLabelspropertyvaluesandhavethemautomaticallyrevertbacktotheirdefaultsonthesubsequent
postback.Thissimplifiesthecodeforshowingastatusmessageinresponsetosomeuseractionthatdisappearson
thesubsequentpostback.Finally,settheStatusLabel controlsCssClass propertytoWarning, whichisthe
nameofaCSSclassdefinedinStyles.css thatdisplaystextinalarge,italic,bold,redfont.
Figure11showstheVisualStudioDesigneraftertheLabelhasbeenaddedandconfigured.
12 of20
Figure11:PlacetheStatusLabel ControlAbovetheTwoPanelControls
Step3:SwitchingBetweentheDisplayandInsertingInterfaces
Atthispointwehavecompletedthemarkupforourdisplayandinsertinginterfaces,butwerestillleftwithtwo
tasks:
l
l
Switchingbetweenthedisplayandinsertinginterfaces
Addingtheproductsintheshipmenttothedatabase
Currently,thedisplayinterfaceisvisiblebuttheinsertinginterfaceishidden.Thisisbecausethe
DisplayInterface PanelsVisible propertyissettoTrue (thedefaultvalue),whiletheInsertingInterface
PanelsVisible propertyissettoFalse.Toswitchbetweenthetwointerfaceswesimplyneedtotoggleeach
controlsVisible propertyvalue.
WewanttomovefromthedisplayinterfacetotheinsertinginterfacewhentheProcessProductShipment button
isclicked.Therefore,createaneventhandlerforthisButtonsClick eventthatcontainsthefollowingcode:
ProtectedSubProcessShipment_Click(senderAsObject,eAsEventArgs)_
HandlesProcessShipment.Click
DisplayInterface.Visible=False
InsertingInterface.Visible=True
EndSub
ReturnToDisplayInterface methodneedstoreturntheWebcontrolstotheirpreeditingstate.Thisinvolves
settingtheDropDownListsSelectedIndex propertiesto0andclearingouttheText propertiesoftheTextBox
controls.
Note:Considerwhatmighthappenifwedidntreturnthecontrolstotheirpreeditingstatebeforereturning
tothedisplayinterface.AusermightclicktheProcessProductShipmentbutton,entertheproductsfrom
theshipment,andthenclickAddProductsfromShipment. Thiswouldaddtheproductsandreturntheuser
tothedisplayinterface.Atthispointtheusermightwanttoaddanothershipment.Uponclickingthe
ProcessProductShipmentbuttontheywouldreturntotheinsertinginterfacebuttheDropDownList
selectionsandTextBoxvalueswouldstillbepopulatedwiththeirpreviousvalues.
ProtectedSubAddProducts_Click(senderAsObject,eAsEventArgs)_
HandlesAddProducts.Click
'TODO:Savetheproducts
'Reverttothedisplayinterface
ReturnToDisplayInterface()
EndSub
ProtectedSubCancelButton_Click(senderAsObject,eAsEventArgs)_
HandlesCancelButton.Click
'Reverttothedisplayinterface
ReturnToDisplayInterface()
EndSub
ConstfirstControlIDAsInteger=1
ConstlastControlIDAsInteger=5
PrivateSubReturnToDisplayInterface()
'Resetthecontrolvaluesintheinsertinginterface
Suppliers.SelectedIndex=0
Categories.SelectedIndex=0
ForiAsInteger=firstControlIDTolastControlID
CType(InsertingInterface.FindControl_
("ProductName"+i.ToString()),TextBox).Text=String.Empty
CType(InsertingInterface.FindControl_
("UnitPrice"+i.ToString()),TextBox).Text=String.Empty
Next
DisplayInterface.Visible=True
InsertingInterface.Visible=False
EndSub
14 of20
Cancel buttonsreturnsyoutothedisplayinterface.
Note:Whileviewingtheinsertinginterface,takeamomenttotestouttheCompareValidatorsontheunit
priceTextBoxes.YoushouldseeaclientsidemessageboxwarningwhenclickingtheAddProductsfrom
Shipmentbuttonwithinvalidcurrencyvaluesorpriceswithavaluelessthanzero.
Figure12:TheInsertingInterfaceisDisplayedAfterClickingtheProcessProductShipmentButton
Step4:AddingtheProducts
AllthatremainsforthistutorialistosavetheproductstothedatabaseintheAddProductsfromShipment
ButtonsClick eventhandler.ThiscanbeaccomplishedbycreatingaProductsDataTable andaddinga
ProductsRow instanceforeachoftheproductnamessupplied.OncetheseProductsRowshavebeenaddedwewill
makeacalltotheProductsBLL classsUpdateWithTransaction methodpassingintheProductsDataTable.
RecallthattheUpdateWithTransaction method,whichwascreatedbackintheWrappingDatabase
ModificationswithinaTransaction tutorial,passestheProductsDataTable totheProductsTableAdapters
UpdateWithTransaction method.Fromthere,anADO.NETtransactionisstartedandtheTableAdatperissuesan
INSERT statementtothedatabaseforeachaddedProductsRow intheDataTable.Assumingallproductsareadded
withouterror,thetransactioniscommitted,otherwiseitisrolledback.
ThecodefortheAddProductsfromShipmentButtonsClick eventhandleralsoneedstoperformabitoferror
checking.SincetherearenoRequiredFieldValidatorsusedintheinsertinginterface,ausercouldenterapricefora
productwhileomittingitsname.Sincetheproductsnameisrequired,ifsuchaconditionunfoldsweneedtoalert
theuserandnotproceedwiththeinserts.ThecompleteClick eventhandlercodefollows:
ProtectedSubAddProducts_Click(senderAsObject,eAsEventArgs)_
HandlesAddProducts.Click
'MakesurethattheUnitPriceCompareValidatorsreportvaliddata...
IfNotPage.IsValidThenExitSub
'AddnewProductsRowstoaProductsDataTable...
DimproductsAsNewNorthwind.ProductsDataTable()
ForiAsInteger=firstControlIDTolastControlID
15 of20
'Readinthevaluesfortheproductnameandunitprice
DimproductNameAsString=CType(InsertingInterface.FindControl_
("ProductName"+i.ToString()),TextBox).Text.Trim()
DimunitPriceAsString=CType(InsertingInterface.FindControl_
("UnitPrice"+i.ToString()),TextBox).Text.Trim()
'EnsurethatifunitPricehasavalue,sodoesproductName
IfunitPrice.Length>0AndAlsoproductName.Length=0Then
'Displayawarningandexitthiseventhandler
StatusLabel.Text="Ifyouprovideaunitpriceyoumustalso
includethenameoftheproduct."
StatusLabel.Visible=True
ExitSub
EndIf
'Onlyaddtheproductifaproductnamevalueisprovided
IfproductName.Length>0Then
'AddanewProductsRowtotheProductsDataTable
DimnewProductAsNorthwind.ProductsRow=products.NewProductsRow()
'Assignthevaluesfromthewebpage
newProduct.ProductName=productName
newProduct.SupplierID=Convert.ToInt32(Suppliers.SelectedValue)
newProduct.CategoryID=Convert.ToInt32(Categories.SelectedValue)
IfunitPrice.Length>0Then
newProduct.UnitPrice=Convert.ToDecimal(unitPrice)
EndIf
'Addany"default"values
newProduct.Discontinued=False
newProduct.UnitsOnOrder=0
products.AddProductsRow(newProduct)
EndIf
Next
'Ifwereachhere,seeiftherewereanyproductsadded
Ifproducts.Count>0Then
'Addthenewproductstothedatabaseusingatransaction
DimproductsAPIAsNewProductsBLL()
productsAPI.UpdateWithTransaction(products)
'Rebindthedatatothegridsothattheproducstjustaddedaredisplayed
ProductsGrid.DataBind()
'Displayaconfirmation(don'tusetheWarningCSSclass,though)
StatusLabel.CssClass=String.Empty
StatusLabel.Text=String.Format(_
"{0}productsfromsupplier{1}havebeen"&_
"addedandfiledundercategory{2}.",_
products.Count,Suppliers.SelectedItem.Text,Categories.SelectedItem.Text)
StatusLabel.Visible=True
'Reverttothedisplayinterface
ReturnToDisplayInterface()
Else
'Noproductssupplied!
16 of20
StatusLabel.Text=
"Noproductswereadded.Pleaseenterthe"&_
"productnamesandunitpricesinthetextboxes."
StatusLabel.Visible=True
EndIf
EndSub
TheeventhandlerstartsbyensuringthatthePage.IsValid propertyreturnsavalueofTrue.IfitreturnsFalse,
thenthatmeansoneormoreoftheCompareValidatorsarereportinginvaliddatainsuchacasewedonotwantto
attempttoinserttheenteredproductsorwellendupwithanexceptionwhenattemptingtoassigntheuserentered
unitpricevaluetotheProductsRowsUnitPrice property.
Next,anewProductsDataTable instanceiscreated(products).AFor loopisusedtoiteratethroughtheproduct
nameandunitpriceTextBoxesandtheText propertiesarereadintothelocalvariables productName and
unitPrice.Iftheuserhasenteredavaluefortheunitpricebutnotforthecorrespondingproductname,the
StatusLabel displaysthemessageIfyouprovideaunitpriceyoumustalsoincludethenameoftheproduct and
theeventhandlerisexited.
Ifaproductnamehasbeenprovided,anewProductsRow instanceiscreatedusingtheProductsDataTables
NewProductsRow method.ThisnewProductsRow instancesProductName propertyissettothecurrentproduct
nameTextBoxwhiletheSupplierID andCategoryID propertiesareassignedtotheSelectedValue propertiesof
theDropDownListsintheinsertinginterfacesheader.Iftheuserenteredavaluefortheproductsprice,itis
assignedtotheProductsRow instancesUnitPrice propertyotherwise,thepropertyisleftunassigned,whichwill
resultinaNULL valuefor UnitPrice inthedatabase.Finally,theDiscontinued andUnitsOnOrder propertiesare
assignedtothehardcodedvaluesFalse and0,respectively.
AfterthepropertieshavebeenassignedtotheProductsRow instanceitisaddedtotheProductsDataTable.
AtthecompletionoftheFor loop,wecheckwhetheranyproductshavebeenadded.Theusermay,afterall,have
clickedtheAddProductsfromShipmentbeforeenteringanyproductnamesorprices.Ifthereisatleastone
productintheProductsDataTable,theProductsBLL classsUpdateWithTransaction methodiscalled.Next,
thedataisreboundtotheProductsGrid GridViewsothatthenewlyaddedproductswillappearinthedisplay
interface.TheStatusLabel isupdatedtodisplayaconfirmationmessageandtheReturnToDisplayInterface is
invoked,hidingtheinsertinginterfaceandshowingthedisplayinterface.
Ifnoproductswereentered,theinsertinginterfaceremainsdisplayedbutthemessageNoproductswereadded.
Pleaseentertheproductnamesandunitpricesinthetextboxesisdisplayed.
Figures13,14,and15showtheinsertinganddisplayinterfacesinaction.InFigure13,theuserhasenteredaunit
pricevaluewithoutacorrespondingproductname.Figure14showsthedisplayinterfaceafterthreenewproducts
havebeenaddedsuccessfully,whileFigure15showstwoofthenewlyaddedproductsintheGridView(thethird
oneisonthepreviouspage).
17 of20
Figure13:AProductNameisRequiredWhenEnteringaUnitPrice
Figure14:ThreeNewVeggiesHaveBeenAddedfortheSupplierMayumis
18 of20
Figure15:TheNewProductsCanBeFoundintheLastPageoftheGridView
Note:Thebatchinsertinglogicusedinthistutorialwrapstheinsertswithinthescopeoftransaction.To
verifythis,purposefullyintroduceadatabaselevelerror.Forexample,ratherthanassigningthenew
ProductsRow instancesCategoryID propertytotheselectedvalueintheCategories DropDownList,
assignittoavaluelikei*5.Herei istheloopindexerandhasvaluesrangingfrom1to5.Therefore,
whenaddingtwoormoreproductsinbatchinsertthefirstproductwillhaveavalid CategoryID value(5),
butsubsequentproductswillhaveCategoryID valuesthatdonotmatchuptoCategoryID valuesinthe
Categories table.TheneteffectisthatwhilethefirstINSERT willsucceed,subsequentoneswillfailwitha
foreignkeyconstraintviolation.Sincethebatchinsertisatomic,thefirstINSERT willberolledback,
returningthedatabasetoitsstatebeforethebatchinsertprocessbegan.
Summary
Overthisandtheprevioustwotutorialswehavecreatedinterfacesthatallowforupdating,deleting,andinserting
batchesofdata,allofwhichusedthetransactionsupportweaddedtotheDataAccessLayerintheWrapping
DatabaseModificationswithinaTransactiontutorial.Forcertainscenarios,suchbatchprocessinguserinterfaces
greatlyimproveenduserefficiencybycuttingdownonthenumberofclicks,postbacks,andkeyboardtomouse
contextswitches,whilealsomaintainingtheintegrityoftheunderlyingdata.
Thistutorialcompletesourlookatworkingwithbatcheddata.Thenextsetoftutorialsexploresavarietyof
advancedDataAccessLayerscenarios,includingusingstoredproceduresintheTableAdaptersmethods,
configuringconnection andcommandlevelsettingsintheDAL,encryptingconnectionstrings,andmore!
HappyProgramming!
AbouttheAuthor
ScottMitchell,authorofsevenASP/ASP.NETbooksandfounderof4GuysFromRolla.com,hasbeenworkingwith
MicrosoftWebtechnologiessince1998.Scottworksasanindependentconsultant,trainer,andwriter.Hislatest
19 of20
bookisSamsTeachYourselfASP.NET2.0in24Hours.Hecanbereachedatmitchell@4GuysFromRolla.com. or
viahisblog,whichcanbefoundat http://ScottOnWriting.NET.
SpecialThanksTo
Thistutorialserieswasreviewedbymanyhelpfulreviewers.LeadreviewersforthistutorialwereHiltonGiesenow
andSrenJacobLauritsen.InterestedinreviewingmyupcomingMSDNarticles?Ifso,dropmealineat
[email protected].
20 of20