dat402 microsoft ® ado.net: blackbelt dat402 microsoft ® ado.net: blackbelt gert e.r. drapers...

39
DAT402 DAT402 Microsoft Microsoft ® ® ADO.NET: ADO.NET: Blackbelt Blackbelt Gert E.R. Drapers Gert E.R. Drapers Architect Architect Microsoft Corp. Microsoft Corp.

Upload: norah-copeland

Post on 26-Dec-2015

218 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

DAT402DAT402

MicrosoftMicrosoft®® ADO.NET: Blackbelt  ADO.NET: Blackbelt 

Gert E.R. DrapersGert E.R. DrapersArchitectArchitectMicrosoft Corp.Microsoft Corp.

Page 2: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

AgendaAgenda

• Common TechniquesCommon Techniques• Optimizing PerformanceOptimizing Performance• Security ConsiderationsSecurity Considerations• QuestionsQuestions

Page 3: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

AgendaAgenda

• Common TechniquesCommon Techniques– Updating from a DataSetUpdating from a DataSet– Server Cursors and ADO.NETServer Cursors and ADO.NET– Using the DataSet as a CacheUsing the DataSet as a Cache– Controlling how XML is generatedControlling how XML is generated– Working with Identity ColumnsWorking with Identity Columns– Handling Large ResultSetsHandling Large ResultSets– Join Queries against a DataSetJoin Queries against a DataSet– RecordsetRecordsetDatasetDataset

• Optimizing PerformanceOptimizing Performance• Security ConsiderationsSecurity Considerations

Page 4: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Updating From A DataSetUpdating From A DataSet

• Use a DataAdapterUse a DataAdapter– Typically one per table to be updatedTypically one per table to be updated– Specify Insert, Update, Delete commandsSpecify Insert, Update, Delete commands• Use CommandBuilder for AdHoc queriesUse CommandBuilder for AdHoc queries

– Designers, toolsDesigners, tools

– Call Update(), passing in DataSet/DataTable to be Call Update(), passing in DataSet/DataTable to be updatedupdated• No persistent connection between DataAdapter and DataSetNo persistent connection between DataAdapter and DataSet

– Can use different DataAdapters for Fill and UpdateCan use different DataAdapters for Fill and Update– Use ExtendedProperties to pass datasource informationUse ExtendedProperties to pass datasource information

Page 5: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Specifying Update CommandsSpecifying Update Commands

• Associate parameters with DataSet ColumnsAssociate parameters with DataSet Columns– Specify SourceColumn propertySpecify SourceColumn property– Parameter values will be set using values from the Parameter values will be set using values from the

Dataset Dataset for each Insert, Update, or Deletefor each Insert, Update, or Delete

'Specify Delete Command'Specify Delete CommandDim delete As New SqlCommand("DeleteOrder", cnn)Dim delete As New SqlCommand("DeleteOrder", cnn)delete.CommandType = CommandType.StoredProceduredelete.CommandType = CommandType.StoredProcedure

'Create a Parameter and associate it with Dataset column'Create a Parameter and associate it with Dataset columnDim param As New SqlParameter("@OrderID", SqlDbType.Int)Dim param As New SqlParameter("@OrderID", SqlDbType.Int)param.SourceColumn = "OrderID"param.SourceColumn = "OrderID"delete.Parameters.Add(param)delete.Parameters.Add(param)

'Set as the Delete Command'Set as the Delete Commandadapter.DeleteCommand = deleteadapter.DeleteCommand = delete

Page 6: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Dim adapter As New SqlDataAdapter()Dim adapter As New SqlDataAdapter()Dim delete As New SqlCommand("DeleteOrder", cnn)Dim delete As New SqlCommand("DeleteOrder", cnn)delete.CommandType = CommandType.StoredProceduredelete.CommandType = CommandType.StoredProceduredelete.Parameters.Add("@OrderID", SqlDbType.Int).SourceColumn = delete.Parameters.Add("@OrderID", SqlDbType.Int).SourceColumn =

"OrderID""OrderID"adapter.DeleteCommand = deleteadapter.DeleteCommand = delete

Dim insert As New SqlCommand("AddOrder", cnn)Dim insert As New SqlCommand("AddOrder", cnn)insert.CommandType = CommandType.StoredProcedureinsert.CommandType = CommandType.StoredProcedureinsert.Parameters.Add("@OrderID", SqlDbType.Int).SourceColumn = insert.Parameters.Add("@OrderID", SqlDbType.Int).SourceColumn =

"OrderID""OrderID"insert.Parameters.Add("@CustD", SqlDbType.Int).SourceColumn = insert.Parameters.Add("@CustD", SqlDbType.Int).SourceColumn =

"CustomerID""CustomerID"insert.Parameters.Add("@Date", SqlDbType.DateTime).Value = insert.Parameters.Add("@Date", SqlDbType.DateTime).Value =

DateTime.NowDateTime.Now

adapter.InsertCommand = insertadapter.InsertCommand = insertDim update As New SqlCommand("UpdateOrder", cnn)Dim update As New SqlCommand("UpdateOrder", cnn)update.CommandType = CommandType.StoredProcedureupdate.CommandType = CommandType.StoredProcedureupdate.Parameters.Add("@OrderID",SqlDbType.Int).SourceColumn="Ordupdate.Parameters.Add("@OrderID",SqlDbType.Int).SourceColumn="Ord

erID"erID"update.Parameters.Add("@CustD",SqlDbType.Int).SourceColumn="Custoupdate.Parameters.Add("@CustD",SqlDbType.Int).SourceColumn="Custo

merID"merID"adapter.UpdateCommand = updateadapter.UpdateCommand = updateadapter.Update(ordersTable)adapter.Update(ordersTable)

Updating ExampleUpdating Example

Page 7: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Optimistic ConcurrencyOptimistic Concurrency• Specify Original values or RowVersion columnSpecify Original values or RowVersion column

– Original values for changes made to data readOriginal values for changes made to data read– RowVersion for any changes made to rowRowVersion for any changes made to row

• Set SourceVersion for original valuesSet SourceVersion for original values

• Account for Nulls in Where clause:Account for Nulls in Where clause:

• Add additional logic in Stored Procedure for handling Add additional logic in Stored Procedure for handling concurrency and conflictsconcurrency and conflicts

WHERE ((Country ISNULL) AND (@Country ISNULL)) OR WHERE ((Country ISNULL) AND (@Country ISNULL)) OR (Country=@Country)(Country=@Country)

Dim update As New SqlCommand("Update Customers (Name) Values " & _ Dim update As New SqlCommand("Update Customers (Name) Values " & _ "(@Name) Where Name=@OldName AND CustID=@ID",cnn)"(@Name) Where Name=@OldName AND CustID=@ID",cnn)

update.Parameters.Add("@Name",SqlDbType.VarChar).SourceColumn = "Name"update.Parameters.Add("@Name",SqlDbType.VarChar).SourceColumn = "Name"update.Parameters.Add("@CustID",SqlDbType.Int).SourceColumn = update.Parameters.Add("@CustID",SqlDbType.Int).SourceColumn = "CustomerID""CustomerID"Dim param = update.Parameters.Add("@OldName",SqlDbType.VarChar)Dim param = update.Parameters.Add("@OldName",SqlDbType.VarChar)param.SourceColumn = "Name"param.SourceColumn = "Name"param.SourceVersion = DataRowVersion.Originalparam.SourceVersion = DataRowVersion.Original

Page 8: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Server Cursors And ADO.NETServer Cursors And ADO.NET

• DataReader versus DataSetDataReader versus DataSet– DataReader is a Forward Only/Read Only "Server Cursor"DataReader is a Forward Only/Read Only "Server Cursor"– Requests Data from Server as read on ClientRequests Data from Server as read on Client

• Buffered in packets at network levelBuffered in packets at network level

– Holds state on the Server until closedHolds state on the Server until closed

• Pessimistic ConcurrencyPessimistic Concurrency– Locking records when read ensures updates don't fail due to concurrency violationsLocking records when read ensures updates don't fail due to concurrency violations– Kills scalability of applicationKills scalability of application– Supported in ADO.NET through transactionsSupported in ADO.NET through transactions

• Scrollable Server CursorsScrollable Server Cursors– Holds State on ServerHolds State on Server– Round-trip per fetch/updateRound-trip per fetch/update– Generally better handled in DataSet or Stored ProcedureGenerally better handled in DataSet or Stored Procedure– Supported in ADO.NET through Cursor DML commandsSupported in ADO.NET through Cursor DML commands

Page 9: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

'Start a transaction and set on Select command'Start a transaction and set on Select commandDim connect = adapter.SelectCommand.ConnectionDim connect = adapter.SelectCommand.Connectionconnect.Open()connect.Open()Dim tran = connect.BeginTransaction(IsolationLevel.Serializable)Dim tran = connect.BeginTransaction(IsolationLevel.Serializable)adapter.SelectCommand.Transaction = tranadapter.SelectCommand.Transaction = tran

'Fill DataSet and make changes'Fill DataSet and make changesadapter.Fill(ds, "Employees")adapter.Fill(ds, "Employees")Dim employee As DataRowDim employee As DataRowFor Each employee In ds.Tables("Employees").RowsFor Each employee In ds.Tables("Employees").Rows employee("Salary") = employee("Salary") * 1.1employee("Salary") = employee("Salary") * 1.1NextNext

'Set the connection and transaction for the update command'Set the connection and transaction for the update commandadapter.UpdateCommand.Connection = connectadapter.UpdateCommand.Connection = connectadapter.UpdateCommand.Transaction = tranadapter.UpdateCommand.Transaction = tran

adapter.Update(ds,"Employees")adapter.Update(ds,"Employees")tran.Commit()tran.Commit()

connect.Close()connect.Close()

Pessimistic ConcurrencyPessimistic Concurrency

Page 10: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

' Declare and open cursor' Declare and open cursorDim cmd As New SqlCommand(Nothing, conn)Dim cmd As New SqlCommand(Nothing, conn)cmd.CommandText = “DECLARE mycursor SCROLLABLE CURSOR FOR select * from cmd.CommandText = “DECLARE mycursor SCROLLABLE CURSOR FOR select * from

Customers”Customers”cmd.ExecuteNonQuery()cmd.ExecuteNonQuery()cmd.CommandText = “OPEN mycursor”cmd.CommandText = “OPEN mycursor”cmd.ExecuteNonQuery()cmd.ExecuteNonQuery()

' Read from cursor' Read from cursorDim dr As SqlDataReaderDim dr As SqlDataReadercmd.CommandText = “FETCH NEXT FROM mycursor”cmd.CommandText = “FETCH NEXT FROM mycursor”While(True)While(True)

dr =cmd.ExecuteReader()dr =cmd.ExecuteReader()if (dr.Read() = false) Then Exit Whileif (dr.Read() = false) Then Exit WhileConsole.WriteLine("CompanyName is " & dr("CompanyName"))Console.WriteLine("CompanyName is " & dr("CompanyName"))dr.Close()dr.Close()

End WhileEnd While

' Update fifth row' Update fifth rowcmd.CommandText = “FETCH ABSOLUTE 5 FROM mycursor”cmd.CommandText = “FETCH ABSOLUTE 5 FROM mycursor”cmd.ExecuteNonQuery()cmd.ExecuteNonQuery()cmd.CommandText = “UPDATE Customers set FirstName = ‘Bill’ WHERE CURRENT cmd.CommandText = “UPDATE Customers set FirstName = ‘Bill’ WHERE CURRENT

OF mycursor”OF mycursor”cmd.ExecuteNonQuery()cmd.ExecuteNonQuery()

' Close the cursor' Close the cursorcmd.CommandText = “CLOSE mycursor; DEALLOCATE mycursor”cmd.CommandText = “CLOSE mycursor; DEALLOCATE mycursor”cmd.ExecuteNonQuery()cmd.ExecuteNonQuery()

Scrollable Server CursorsScrollable Server Cursors

Page 11: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Using The Dataset As A CacheUsing The Dataset As A Cache

• DataSet optimized for multi-threaded read accessDataSet optimized for multi-threaded read access– Can put in ASP.NET cacheCan put in ASP.NET cache– Doesn't take locksDoesn't take locks– Need to synchronize writesNeed to synchronize writes– Clone, Update, and replaceClone, Update, and replace

Function GetCategories() As DataSetFunction GetCategories() As DataSet'See if DataSet exists in Cache'See if DataSet exists in CacheDim categories As DataSet = Cache("CategoriesDS")Dim categories As DataSet = Cache("CategoriesDS")if (categories Is Nothing) ' not in cache, create if (categories Is Nothing) ' not in cache, create DataAdapter and Load DataSetDataAdapter and Load DataSet

Dim adapter As new SqlDataAdapter("Select CategoryName Dim adapter As new SqlDataAdapter("Select CategoryName from Categories",cnn)from Categories",cnn)

adapter.Fill(categories)adapter.Fill(categories)'Put Categories Dataset into Cache'Put Categories Dataset into CacheCache("CategoriesDS")=categoriesCache("CategoriesDS")=categories

End IfEnd Ifreturn categoriesreturn categories

End FunctionEnd Function

Page 12: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Controlling how XML is GeneratedControlling how XML is Generated

• DataSet lets you control how XML is generatedDataSet lets you control how XML is generated• Name, Namespace properties on DataSet, Name, Namespace properties on DataSet,

DataTable, DataColumnDataTable, DataColumn• MappingType property on DataColumn defines MappingType property on DataColumn defines

how data is writtenhow data is written– Element, Attribute, SimpleType, HiddenElement, Attribute, SimpleType, Hidden

• Nested Property on DataRelation controls how Nested Property on DataRelation controls how children are writtenchildren are written

Page 13: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Controlling how XML is GeneratedControlling how XML is Generated

' Write out CustomerID, OrderID as Attributes' Write out CustomerID, OrderID as Attributesds.Tables("Customers").Columns("CustomerID").ColumnMapping = ds.Tables("Customers").Columns("CustomerID").ColumnMapping =

MappingType.AttributeMappingType.Attributeds.Tables("Orders").Columns("OrderID").ColumnMapping = ds.Tables("Orders").Columns("OrderID").ColumnMapping =

MappingType.AttributeMappingType.Attribute

' Write out Orders as children of Customers' Write out Orders as children of Customersds.Relations("cust_orders").Nested = Trueds.Relations("cust_orders").Nested = True

<?xml version="1.0" standalone="yes"?><?xml version="1.0" standalone="yes"?><CustomerOrders><CustomerOrders> <Customers CustomerID="GROSR"><Customers CustomerID="GROSR"> <ContactName>Manuel Pereira</ContactName><ContactName>Manuel Pereira</ContactName> <Orders OrderID="10268"><Orders OrderID="10268"> <CustomerID>GROSR</CustomerID><CustomerID>GROSR</CustomerID> <OrderDate>1996-07-30</OrderDate><OrderDate>1996-07-30</OrderDate> </Orders></Orders> </Customers></Customers></CustomerOrders></CustomerOrders>

Page 14: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Working With Identity ColumnsWorking With Identity Columns

• Issue: Primary Keys must be unique across Issue: Primary Keys must be unique across consumers in order to merge back to databaseconsumers in order to merge back to database

• Solution #1: Use a GUID as the Primary Key Solution #1: Use a GUID as the Primary Key where possiblewhere possible– Can be generated on the Client or ServerCan be generated on the Client or Server• Guaranteed to be uniqueGuaranteed to be unique

– Doesn’t change when updated to the ServerDoesn’t change when updated to the Server• No fixup required for child rowsNo fixup required for child rows

Page 15: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Working With Identity ColumnsWorking With Identity Columns

• Issue: Primary Keys must be unique across consumers in order to Issue: Primary Keys must be unique across consumers in order to merge back to databasemerge back to database

• Solution #2: If you are stuck with an AutoIncrement Primary Key…Solution #2: If you are stuck with an AutoIncrement Primary Key…– First, make sure Client value doesn't conflict with Server valueFirst, make sure Client value doesn't conflict with Server value

• Set AutoIncrement Seed, Step to -1 on DataSetSet AutoIncrement Seed, Step to -1 on DataSet

– To update values in Dataset, select back the ID in your InsertCommandTo update values in Dataset, select back the ID in your InsertCommand• Update the inserted row with the new valueUpdate the inserted row with the new value

– Insert Parent rows before Child RowsInsert Parent rows before Child Rows• Use UpdateRule.CascadeUse UpdateRule.Cascade

– If you are merging with the original DataSet, prevent AcceptChanges from If you are merging with the original DataSet, prevent AcceptChanges from being called on Inserted rowbeing called on Inserted row• Specify SkipCurrentRow in OnRowUpdated EventhandlerSpecify SkipCurrentRow in OnRowUpdated Eventhandler

Page 16: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Sub UpdateData(table As DataTable)

' Set InsertCommand with returned Identity Dim insert As New SqlCommand( _

"Insert into Orders(OrderID,Date) values @OrderID, @Date)" _& ";Select SCOPE_IDENTITY() as OrderID",cnn)

insert.Parameters.Add("@OrderID",SqlDbType.Int).SourceColumn="OrderID" insert.Parameters.Add("@Date",SqlDbType.DateTime).Value = DateTime.Now adapter.InsertCommand = insert

' Set UpdateRowSource and Register RowUpdatedEventHandler

insert.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord AddHandler adapter.RowUpdated, _

New SqlRowUpdatedEventHandler(AddressOf myHandler)

DataAdapter.Update(table)End Sub

Shared Sub myHandler(adapter as Object, e As SqlRowUpdatedEventArgs) ' Don't call AcceptChangese.Status = UpdateStatus.SkipCurrentRow

End Sub

Inserting AutoIncrement ValuesInserting AutoIncrement Values

Page 17: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Refreshing Data In The DataSetRefreshing Data In The DataSet

• To update DataSet with current values from the To update DataSet with current values from the Database valuesDatabase values– Specify a Primary Key on the TableSpecify a Primary Key on the Table– Use Adapter.Fill()Use Adapter.Fill()• Fill will update existing values if you have a Primary keyFill will update existing values if you have a Primary key

• To update original values but preserve changesTo update original values but preserve changes– Fill a new DataSet and use DataSet.Merge() with Fill a new DataSet and use DataSet.Merge() with

PreserveChanges=truePreserveChanges=true

Page 18: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Handling Large ResultSetsHandling Large ResultSets• Select just the data the user needsSelect just the data the user needs– User rarely wants to scroll through >100 recordsUser rarely wants to scroll through >100 records

• Call Cancel() on command to dispose of data Call Cancel() on command to dispose of data beyond what is readbeyond what is read

• Page through large resultsPage through large results– Use TOP n in SQL ServerUse TOP n in SQL Server– Use MaxRows for other databasesUse MaxRows for other databases– Paging by Ordinal range (i.e., records 91-100)Paging by Ordinal range (i.e., records 91-100)

– Paging by value range (i.e., M-N)Paging by value range (i.e., M-N)• Parameterized Where clauseParameterized Where clause

SELECT TOP 10 * FROM SELECT TOP 10 * FROM (SELECT TOP 100 ProductName, UnitPrice FROM Products ORDER BY (SELECT TOP 100 ProductName, UnitPrice FROM Products ORDER BY UnitPrice ASC) AS ProductsUnitPrice ASC) AS ProductsORDER BY UnitPrice DESCORDER BY UnitPrice DESC

SELECT TOP 10 ProductName, UnitPrice FROM Products SELECT TOP 10 ProductName, UnitPrice FROM Products WHERE ProductName > @PreviousName ORDER BY ProductName ASC AS WHERE ProductName > @PreviousName ORDER BY ProductName ASC AS ProductsProducts

Page 19: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Join Queries Against DataSetJoin Queries Against DataSet• Use Relations to navigate from parent to childUse Relations to navigate from parent to child

– Restriction: Can’t limit parent based on child valuesRestriction: Can’t limit parent based on child values

• Use XmlDataDocumentUse XmlDataDocument– X/Path queries can be hierarchicalX/Path queries can be hierarchical– Can get DataRows corresponding to returned ElementsCan get DataRows corresponding to returned Elements

Dim nodeslist = xmlData.SelectNodes("//Customers/Orders[@State=WA]")

Dim customer, order As DataRowFor Each customer in CustomerTable.Select("State='WA'")

Console.WriteLine("Customer: " & customer("ContactName"))For Each order in customer.GetChildRows("custord")

Console.WriteLine("Order Amount = " & order("Amount"))Next

Next

Dim node As XmlNodeDim customer as DataRowFor Each node in nodelist

customer = xmlData.GetRowFromElement(node)Next

Page 20: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

RecordSet RecordSet DataSetDataSet

• Getting Data From a RecordSetGetting Data From a RecordSet– Use the OleDbDataAdapter.Fill() methodUse the OleDbDataAdapter.Fill() method–

– Persist the RecordSet as XML and load into the DataSetPersist the RecordSet as XML and load into the DataSet• Use an XSL/T for best resultsUse an XSL/T for best results

• Getting Data From a DataSet to a RecordSetGetting Data From a DataSet to a RecordSet– Write an XSL Transform to do the conversionWrite an XSL Transform to do the conversion

• We hope to provide one of these in the futureWe hope to provide one of these in the future– Walk through the DataSet and generate the XDR description then write out the XML in Walk through the DataSet and generate the XDR description then write out the XML in

attribute-centric formatattribute-centric format• Sample coming soon…Sample coming soon…

Dim rs As New ADODB.Recordset() Dim rs As New ADODB.Recordset() rs.Open("Select * from Orders", "Data Source=localhost;Integrated rs.Open("Select * from Orders", "Data Source=localhost;Integrated Security=true")Security=true")Dim adapter As New OleDbDataAdapter()Dim adapter As New OleDbDataAdapter()adapter.Fill(ds, rs, "Orders")adapter.Fill(ds, rs, "Orders")

Dim ds As New DataSet()Dim ds As New DataSet()ds.ReadXml("rsOrders.xml)ds.ReadXml("rsOrders.xml)

Page 21: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

AgendaAgenda

• Common TechniquesCommon Techniques• Optimizing PerformanceOptimizing Performance– Optimizing Data RetrievalOptimizing Data Retrieval– Using Schema at Design TimeUsing Schema at Design Time– Using BatchesUsing Batches– Looking Up Values in the DataSetLooking Up Values in the DataSet– Provider specific OptimizationsProvider specific Optimizations

• Security ConsiderationsSecurity Considerations• QuestionsQuestions

Page 22: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Optimizing Data RetrievalOptimizing Data Retrieval

• Use ExecuteNonQuery if no results to be returnedUse ExecuteNonQuery if no results to be returned– DDL commands,Inserts, Updates, DeletesDDL commands,Inserts, Updates, Deletes– Non-result returning Stored Procedures (parameters ok)Non-result returning Stored Procedures (parameters ok)

• Return single set of values using Output ParametersReturn single set of values using Output Parameters

Dim numRowsAffected As Integer = cmd.ExecuteNonQuery()Dim numRowsAffected As Integer = cmd.ExecuteNonQuery()

cmd.CommandText = _cmd.CommandText = _"Select @ContactName = ContactName From Customers where "Select @ContactName = ContactName From Customers where

CustomerID = 'GROSR'"CustomerID = 'GROSR'"Dim param = Dim param = cmd.Parameters.Add("@ContactName",SqlDbType.VarChar,25)cmd.Parameters.Add("@ContactName",SqlDbType.VarChar,25)

param.Direction = ParameterDirection.Outputparam.Direction = ParameterDirection.Outputcmd.ExecuteNonQuery()cmd.ExecuteNonQuery()Console.WriteLine("Contact Name = "& param.Value)Console.WriteLine("Contact Name = "& param.Value)

Page 23: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Efficiently Retrieving BLOBsEfficiently Retrieving BLOBs

• Use CommandBehavior.SequentialAccessUse CommandBehavior.SequentialAccess– Must retrieve columns in orderMust retrieve columns in order– No buffering of column valuesNo buffering of column values

Dim cmd As New SqlCommand( "Select * from Employees", Dim cmd As New SqlCommand( "Select * from Employees", cnn)cnn)Dim results = Dim results = cmd.ExecuteReader(CommandBehavior.SequentialAccess)cmd.ExecuteReader(CommandBehavior.SequentialAccess)Dim i As IntegerDim i As IntegerWhile(results.Read()) While(results.Read())

For i=0 to results.FieldCountFor i=0 to results.FieldCountConsole.Write("\t "& results(i))Console.Write("\t "& results(i))Console.WriteLine()Console.WriteLine()

NextNextEnd WhileEnd While

Page 24: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Use Metadata At Design Time Use Metadata At Design Time • DataReaderDataReader

– Strongly Typed Ordinal accessorsStrongly Typed Ordinal accessors– Dim name As String = dr.GetString(0)Dim name As String = dr.GetString(0)

• DataSetDataSet– Load, don't infer, schemaLoad, don't infer, schema

• Data AdapterData Adapter– Don’t use CommandBuilderDon’t use CommandBuilder

• Specify insert,update,delete commands when knownSpecify insert,update,delete commands when known

– Don’t use CommandBuilder.DeriveParameters()Don’t use CommandBuilder.DeriveParameters()• Specify Parameter information when knownSpecify Parameter information when known

– Don’t use MissingSchemaAction.AddWithKeyDon’t use MissingSchemaAction.AddWithKey• Specify Primary Key information when knownSpecify Primary Key information when known

– custTable.PrimaryKey = custTable.Columns("CustID")custTable.PrimaryKey = custTable.Columns("CustID")– Don’t add Primary Key if not necessaryDon’t add Primary Key if not necessary

• Necessary when Updating,Refreshing,Merging valuesNecessary when Updating,Refreshing,Merging values

Page 25: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Retrieving Multiple ResultsRetrieving Multiple Results• Specify Batch statement or stored procedureSpecify Batch statement or stored procedure• Use NextResult() to move to next set of resultsUse NextResult() to move to next set of results

Dim fMoreResults As Boolean = trueDim fMoreResults As Boolean = trueDim field As IntegerDim field As IntegerWhile(fMoreResults) While(fMoreResults)

For field = 0 To dr.FieldCount For field = 0 To dr.FieldCount Console.Write("/t"+dr.GetName(field)) Console.Write("/t"+dr.GetName(field))

NextNextConsole.WriteLine()Console.WriteLine()While(dr.Read())While(dr.Read())

For field = 0 to dr.FieldCountFor field = 0 to dr.FieldCountConsole.Write("/t"+dr(field))Console.Write("/t"+dr(field))

NextNextConsole.WriteLine()Console.WriteLine()

End WhileEnd WhilefMoreResults = dr.NextResult()fMoreResults = dr.NextResult()

End WhileEnd While

Page 26: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Populating Multiple DataTablesPopulating Multiple DataTables• Retrieve multiple results in a single callRetrieve multiple results in a single call– Execute Batch statement or stored procdureExecute Batch statement or stored procdure

• Map results to appropriate tables using tablemappingsMap results to appropriate tables using tablemappings

• Use ExecuteXmlReader to retrieve hierarchical resultsUse ExecuteXmlReader to retrieve hierarchical results– Load with ReadXml using XmlReadMode.FragmentLoad with ReadXml using XmlReadMode.Fragment

• Submit updates in batchesSubmit updates in batches– Sample batch update example available soon…Sample batch update example available soon…– Or save as DiffGram and send to SqlXmlOr save as DiffGram and send to SqlXml

Dim adapter As New SqlDataAdapter( _Dim adapter As New SqlDataAdapter( _"SELECT * FROM customers; SELECT * FROM orders",cnn)"SELECT * FROM customers; SELECT * FROM orders",cnn)

adapter.TableMappings.Add("Table1","Customer")adapter.TableMappings.Add("Table1","Customer")adapter.TableMappings.Add("Table2","Orders")adapter.TableMappings.Add("Table2","Orders")adapter.Fill(myDataSet)adapter.Fill(myDataSet)

Page 27: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Looking Up Values In The DatasetLooking Up Values In The Dataset

• Searching for Results within a DataSetSearching for Results within a DataSet– DataTable.Find() for searching on PK valuesDataTable.Find() for searching on PK valuesDim customer = customerTable.Rows.Find("GROSR")Dim customer = customerTable.Rows.Find("GROSR")

– DataView.Select() for repeated non-PK queriesDataView.Select() for repeated non-PK queries• Sort DataView by search fieldsSort DataView by search fields• DataView builds an index for sorted columnsDataView builds an index for sorted columnsDim customerView As New DataView(customerTable)Dim customerView As New DataView(customerTable)customerView.Sort = "State“customerView.Sort = "State“Dim customers = customerView.FindRows("CA")Dim customers = customerView.FindRows("CA")

• Pass Table, filter, sort, RowState to constructorPass Table, filter, sort, RowState to constructorDim view As New DataView( Dim view As New DataView( __

customerTable,customerTable, __"Country=USA","Country=USA", __"Region","Region", __DataViewRowState.CurrentRows )DataViewRowState.CurrentRows )

Page 28: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Coding To Different ProvidersCoding To Different Providers

• Use Activator to create root class Use Activator to create root class (DbConnection)(DbConnection)

• Code to InterfacesCode to Interfaces• Use CreateCommand() to get IDbCommandUse CreateCommand() to get IDbCommand• Take into account provider differencesTake into account provider differences– SqlClient named parameters versus OLE DB SqlClient named parameters versus OLE DB

positional parameterspositional parameters– CommandBuilder classesCommandBuilder classes

Page 29: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Provider Specific OptimizationsProvider Specific Optimizations

• SqlClient .NET Data ProviderSqlClient .NET Data Provider– Use CommandType.StoredProcedure to execute stored procsUse CommandType.StoredProcedure to execute stored procs

• More efficient than executing command call{} or Exec syntaxMore efficient than executing command call{} or Exec syntax

– Set max connection lifetime for load balancingSet max connection lifetime for load balancing• Times out valid connections in order to balance across back-endsTimes out valid connections in order to balance across back-ends

• OLE DB .NET Data ProviderOLE DB .NET Data Provider– Use specific provider where availableUse specific provider where available

• For example, the SqlClient .NET Data Provider…For example, the SqlClient .NET Data Provider…

– Specify type, size, precision, and scale of parametersSpecify type, size, precision, and scale of parameters• Otherwise we rebind w/each executeOtherwise we rebind w/each execute

– Connection.State is expensiveConnection.State is expensive• Round-trip to check stateRound-trip to check state• Better to listen to change event to track stateBetter to listen to change event to track state

Page 30: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

AgendaAgenda

• Common TechniquesCommon Techniques• Optimizing PerformanceOptimizing Performance• Security ConsiderationsSecurity Considerations– Use Integrated SecurityUse Integrated Security– Avoid String ConcatenationAvoid String Concatenation– Use Stored ProceduresUse Stored Procedures– Set Privileges AppropriatelySet Privileges Appropriately

• QuestionsQuestions

Page 31: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Use Integrated SecurityUse Integrated Security

• Don’t use sa account! (especially w/no password)Don’t use sa account! (especially w/no password)connect.ConnectionString = connect.ConnectionString = "server=localhost;uid=sa;password=""server=localhost;uid=sa;password="

• Don’t embed password in connection stringDon’t embed password in connection stringconnect.ConnectionString = connect.ConnectionString = "server=localhost;uid=sa;password=pwd""server=localhost;uid=sa;password=pwd"

• Don’t concatenate UID/Password from user into connection Don’t concatenate UID/Password from user into connection string (without validating input)string (without validating input)connect.ConnectionString = connect.ConnectionString = "server=localhost;uid=sa;password="&pwd"server=localhost;uid=sa;password="&pwd

– pwd may be “pwd;Default Database = ‘master’”pwd may be “pwd;Default Database = ‘master’”• Use Integrated SecurityUse Integrated Security

connect.ConnectionString = connect.ConnectionString = "server=localhost;Integrated Security=SSPI""server=localhost;Integrated Security=SSPI"

Page 32: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Avoid String ConcatenationAvoid String Concatenation

• Don’t concatenate user strings into command textDon’t concatenate user strings into command textcmd.CommandText = “select * from Customers where cmd.CommandText = “select * from Customers where CustomerID = "&custIDCustomerID = "&custID

– user may set custID = ‘“GROSR’; Drop Table Customers;”user may set custID = ‘“GROSR’; Drop Table Customers;”• InsteadInstead– Have user select string from an enumeration, rather than Have user select string from an enumeration, rather than

enter free textenter free text– Better yet; pass strings as Parameters:Better yet; pass strings as Parameters:

cmd.CommandText = “select * from Customers Wherecmd.CommandText = “select * from Customers WhereCustomerID = @CustID“CustomerID = @CustID“

cmd.Parameters.Add("@CustID",custID)cmd.Parameters.Add("@CustID",custID)

Page 33: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Use Stored ProceduresUse Stored Procedures

• Controls what data user accesses Controls what data user accesses and howand how

• Allows privileges to be set on Allows privileges to be set on Stored ProcedureStored Procedure

• Can enforce additional business logicCan enforce additional business logic• Added protection from malicious Added protection from malicious

string concatenationstring concatenation– Values passed as parametersValues passed as parameters– Validate strings passed to Stored ProcedureValidate strings passed to Stored Procedure

Page 34: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Set Privileges AppropriatelySet Privileges Appropriately

• Create user appropriate to client roleCreate user appropriate to client role– Don’t just use “sa” for everything!Don’t just use “sa” for everything!

• Set Privileges on resources accessedSet Privileges on resources accessed– Stored ProceduresStored Procedures– TablesTables– ColumnsColumns

Page 35: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

• Whitepapers:Whitepapers:– ADO.NET for the ADO Programmer:ADO.NET for the ADO Programmer:

http://msdn.microsoft.com/library/en-us/dndotnet/html/ADONETProg.asphttp://msdn.microsoft.com/library/en-us/dndotnet/html/ADONETProg.asp

– ADO.NET Best Practices (coming soon):ADO.NET Best Practices (coming soon):

http://msdn.microsoft.com/library/en-us/dndotnet/html/ADONETBest.asphttp://msdn.microsoft.com/library/en-us/dndotnet/html/ADONETBest.asp

• ADO.NET On-Line Chat TranscriptADO.NET On-Line Chat Transcripthttp://msdn.microsoft.com/chats/vstudio/vstudio_012402.asphttp://msdn.microsoft.com/chats/vstudio/vstudio_012402.asp

• The .NET Show: ADO.NET:The .NET Show: ADO.NET:http://msdn.microsoft.com/theshow/Episode017/default.asphttp://msdn.microsoft.com/theshow/Episode017/default.asp

Additional InformationAdditional Information

Page 36: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Questions?Questions?

Page 37: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Resources from Microsoft PressResources from Microsoft Press

For more information please visit the TechEd Bookshop.For more information please visit the TechEd Bookshop.www.microsoft.com/mspresswww.microsoft.com/mspress

ADO .NET

Page 38: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp

Don’t forget to complete the Don’t forget to complete the on-line Session Feedback form on-line Session Feedback form on the Attendee Web siteon the Attendee Web site

https://web.mseventseurope.com/teched/https://web.mseventseurope.com/teched/

Page 39: DAT402 Microsoft ® ADO.NET: Blackbelt DAT402 Microsoft ® ADO.NET: Blackbelt Gert E.R. Drapers Architect Microsoft Corp