Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
1,39 MB
Nội dung
The following shows the code for the RunSQLParamet erQueryWithPassedParam s
procedure. The lines that change from the RunSQLParameterQuery procedure in
the preceding section appear in bold. Notice just four lines change. These are
mostly for receiving and using the passed string variables that specify the query
syntax and t he parameter value. The RootTag property assignment changes to
make it appropriate for any SQL query string. Aside from these minor changes,
there is nothing more to updating the earlier procedure so that it can
accomm odate any SQL query string.
Sub RunSQLParameterQueryWithPassedParams( _
ByVal strSQL As String, _
ByVal strPrm1Value As String)
’Specify connection string for SqlXmlCommand.
Dim cnn1String As String = _
"Provider=SQLOLEDB;Server=(local);" & _
"database=Northwind;" & _
"Integrated Security=SSPI"
’Specify connection for cmd1 SqlXmlCommand object
Dim cmd1 As SqlXmlCommand = _
New Microsoft.Data.SqlXml.SqlXmlCommand(cnn1String)
’Designate data source for cmd1 with a parameter.
cmd1.RootTag = "MyRoot"
cmd1.CommandType = SqlXmlCommandType.Sql
cmd1.CommandText = strSQL
’Create a parameter for cmd1 and assign it a value.
Dim prm1 As SqlXmlParameter
prm1 = (cmd1.CreateParameter())
prm1.Value = strPrm1Value
’Declare and instantiate a stream in memory and
’populate it with the XML result set from cmd1.
Dim stm1 As New System.IO.MemoryStream()
stm1 = cmd1.ExecuteStream()
’Copy result set in stream to a stream reader
’to display stream contents in a message box.
Dim srd1 As New System.IO.StreamReader(stm1)
MsgBox(srd1.ReadToEnd)
srd1.Close()
End Sub
The I nt erplay Betw een XML and Da ta Set s
XML docum ents and ADO.NET data sets interact with one another in multiple
ways. Understanding these interactions and knowing how to put them to use can
help you query and manipulate data both locally on a client’s workstation and on
a database server. This section provides a selection of samples to show how to
use XML documents with data sets for these purposes. As with many topics
addressed by this book, the presentation isn’t m eant to provide exhaustive
coverage of every possible feature on a topic. Instead, the section aim s to
provide a firm foundation that will equip you to go on and learn more in whatever
directions your needs dictate.
Creat ing Hiera r chical XML Docum ents
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
One of the really valuable aspects of the DataSet object in ADO.NET is that it is
XML-based. What this m eans is that you can manipulate the elements within a
data set and indirectly m odify XML structures. This feature is particularly
beneficial when working with m ultitable row sources that have parent -child
relationships because it relieves developers from representing these com plex
relationships in XSD schemas. Although ADO.NET and XML are relatively new to
many VisualBasic developers, the object m odel for data sets in ADO.NET makes
it relatively more fam iliar to those with any background in manipulating objects.
See Chapter 10 for a general review of ADO.NET objects. Figure 10-1 provides an
overview of the DataSet object model, and numerous code samples throughout
Chapter 10 demonstrate ADO.NET programm ing topics, including the Dat aSet
object and its hierarchically dependent objects.
A Dat aSet object and its associated XML docum ent are like two sides of the same
coin. With the Writ eXm l method for a DataSet obj ect, you can persist both the
contents of an XML document and the underlying schema for the docum ent. In
addition, when a data set has changes not comm itted to a remote database, you
can generate via the WriteXm l method the DiffGram representing the data set
with its uncommitted changes. Recall that a DiffGram contains current values as
well as previous values. The DiffGram is readily available because ADO.NET
conveys changes from a client to a SQLServer instance via DiffGrams.
The sample in this sect ion dem onstrates how to create a three-tiered data set
based on three tables from t he Northwind database. These tables are the
Custom ers, Orders, and Order Details tables. Individual customers are parents of
individual orders, and orders, in turn, are parents of order details, or line items
within an order. This pair of nested relations is the kind of structure that XML
documents represent especially well because the document shows the actual
nesting instead of a single flat rowset.
The sample relies on two procedures. The first procedure,
SaveThreeTierDasAsXm lDocum ent, calls a second procedure that generates a
data set and then persists the data set as an XML document. By using the
WriteXm l method, the SaveThreeTierDasAsXm lDocument procedure avoids a
reliance on SQLXML Managed Classes. This means the techniques demonstrated
in this chapter are relatively robust in that they can work with any data source to
which ADO.NET can connect. I n addition, the procedures demonstrat ed for the
Dat aSet object don’t require t he installation of either Web Release 2 or Web
Release 3, as is necessary for the use of Managed Classes. The second procedure,
Creat eThreeTierDataSet, is a function procedure that returns a DataSet object to
the procedure that calls it. It is this returned data set that the first procedure
persists as an XML document in a file.
The SaveThreeTierDasAsXm lDocument procedure starts by instantiating a
Dat aSet object and populating it with the data set returned by the Creat e-
ThreeTierDat aSet function procedure. After populating the data set, the
procedure prepares to persist it as a file with Unicode characters. These actions
take several steps. The procedure starts the process by assigning the nam e of the
XML docum ent to a string variable (str1). Next the procedure instantiates a
FileSt ream object (fst 1) to hold the file containing the XML document. Then the
procedure instantiates an Xm lTextWriter object (t xw1) to copy the XML within the
data set to the FileSt ream object. The WriteXm l method uses txw1 as one of its
two arguments for copying the XML from t he data set to the file. The other
argument, which is Xm lWriteMode.Writ eSchem a in this case, determines how the
WriteXm l method conveys content from the data set to the file. The
Xm lWrit eMode.WriteSchem a argument directs the Writ eXm l method to start by
copying the schema for the docum ent and then follow the schema with the
contents of the XML document. After writing the document, the procedure frees
resources and returns control to the procedure by closing both the Xm lTextWr iter
and FileSt ream objects.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
The Creat eThreeTierDat aSet procedure starts by instantiating a connection object
and opening it so that the connection points to the Northwind database. The
procedure next instantiates a DataSet object (das1) and uses the connection
object to connect a SqlDataAdapter obj ect (dap1) with the Cust om ers table in the
Northwind database. Then the procedure copies the Customers table rows into a
data table named Custom ers within das1 by invoking the Fill method for the dap1
object. After adding the Cust om ers table from the Northwind database to the
das1 data set, the procedure points dap1 to the Orders table in the Northwind
database. Then it adds the Orders table to das1. It repeats the process a third
and final time to create an OrderDetails data table in das1 with the column values
from the Order Details table in the Northwind database.
At the end of these three invocations of the Fill method, the das1 data set
contains three unrelated tables. However, we need DataRelation objects to
specify the hierarchical relat ionship between tables. In fact, das1 needs two
Dat aRelation objects. One DataRelat ion object expresses the relationship between
the Cust om ers and Orders data tables. A second Dat aRelation object represents
the relationship between the Orders and OrderDetails data tables. The procedure
builds t he first DataRelation object by invoking the Add method for the Relations
collection of the das1 data set. The first argument, which is a string with the
value “CustOrders”, names the DataRelation object. The next two arguments
identify the columns used to join the two data tables. By setting the Nested
property for the DataRelation object to True, you cause the XML document to
show orders nested within customers. The default value for the Nested property is
False. I n this case, the Wr iteXm l method shows two sets of column values
without any nesting of column values from one data table within those of another
data table. By invoking the Add method a second time for the Relations collection
in the das1 data set, the procedure creates a second data relationship expressing
the parent-child structure between the Orders and Order Det ails data tables.
Finally the Creat eThreeTierDataSet procedure concludes by invoking the Return
statem ent to pass the das1 data set back to the procedure that called it.
Sub SaveThreeTierDasAsXmlDocument()
’Declare and instantiate the das1 data set and
’populate it with the return data set from
’the CreateThreeTierDataSet function procedure.
Dim das1 As New DataSet()
das1 = CreateThreeTierDataSet()
’Declare string for filename to hold file stream
’based on XmlTextWriter with contents of das1 data set.
Dim str1 As String = _
"c:\SQL Server Development with VBDotNet\" & _
"Chapter12\myCustomersSchema.xml"
Dim fst1 As New System.IO.FileStream _
(str1, System.IO.FileMode.Create)
Dim txw1 As New System.Xml.XmlTextWriter _
(fst1, System.Text.Encoding.Unicode)
’Write from das1 the XML along with schema.
das1.WriteXml(txw1, XmlWriteMode.WriteSchema)
’Close TextWriter and FileStream.
txw1.Close()
fst1.Close()
End Sub
Function CreateThreeTierDataSet()
’Open connection to northwind database.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Dim cnn1 As SqlConnection = _
New SqlConnection( _
"Data Source=localhost;" & _
"Initial Catalog=northwind;" & _
"Integrated Security=SSPI")
cnn1.Open()
’Declare and instantiate a data set (das1)
Dim das1 As DataSet = New DataSet("CustomerOrders")
’Declare and instantiate a data adapter (dap1) to fill
’the Customers data table in das1.
Dim dap1 As SqlDataAdapter = _
New SqlDataAdapter( _
"SELECT CustomerID, CompanyName, ContactName, Phone " & _
"FROM Customers", cnn1)
dap1.Fill(das1, "Customers")
’Re-use dap1 to fill the Orders data table in das1.
dap1.SelectCommand.CommandText = _
"SELECT OrderID, OrderDate, CustomerID FROM Orders"
dap1.Fill(das1, "Orders")
’Re-use dap1 to fill the OrderDetails data table in das1.
dap1.SelectCommand.CommandText = _
"SELECT * FROM [Order Details]"
dap1.Fill(das1, "OrderDetails")
’Close the connection.
cnn1.Close()
’Specify a relationship between Customers and Orders
’data tables with orders elements nesting within
’customers elements.
das1.Relations.Add("CustOrders", _
das1.Tables("Customers").Columns("CustomerID"), _
das1.Tables("Orders").Columns("CustomerID")). _
Nested = True
’Specify a relationship between Orders and
’OrderDetails data tables with OrderDetails elements
’nesting within orders elements.
das1.Relations.Add("OrderDetail", _
das1.Tables("Orders").Columns("OrderID"), _
das1.Tables("OrderDetails").Columns("OrderID"), _
False).Nested = True
Return das1
End Function
When the SaveThreeTierDasAsXm lDocum ent procedure invokes the WrileXxm l
method with its second argument equal to Xm lWrit eMode.Wr iteSchem a, the
method actually writes two documents in one. The XSD schema for the XML
argument appears before the actual data. The .NET documentation refers to this
kind of schema as an inline schema because it appears in line wit h the XML data
that follows it. The schema for the XML docum ent corresponding to das1 is
reasonably complex because it specifies colum ns from three tables, two data
relationship specifications, and supporting elements, such as constraints to
enable the DataRelation objects. Figures 12-6 and 12-7 show portions of the
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
schema in browser windows; the schema is t oo long to fit in one window. This
schema appears at the beginning of the XML document named in the Save-
ThreeTierDasAsXm lDocument procedure. The XML document’s filename is
myCust omersSchem a.xml in the c: \ SQLServer Development with
VBDotNet\ Chapter12 folder. In testing the application on your system, you may
care to change the destinat ion folder for the XML document to a folder that you
already have on your workstation.
Figure 1 2 - 6 . The first part of th e inline schem a for the XM L d ocum e nt in
the m yCust om ersSche m a .xm l file .
Figure 1 2 - 7 . The second part of t he inline sche m a for the XM L docum ent
in t h e m y Custom ersSchem a .x m l file.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
As you can see from the schema’s length and complexity, it is of value to be able
to write the schema automatically. Creating a data set in code should be fairly
straightforward by this point in the book. In any event, if you are building
solutions with ADO.NET, it is highly likely that you will gain a com fort level with
building data sets programmatically. Therefore, using a program matically created
data set as the basis for a schema may be a useful process if you aren’t handy at
specifying XSD schem as from scratch. In fact, writing out the schemas and
correlating them with the design of your data sets may be a way to have Visual
Basic .NET teach you XSD syntax so that you can eventually write your own
complex schemas from scratch. Figure 12-8 shows an excerpt from the beginning
of the XML data in myCustom ersSchem a.xm l. You can see all of the first order
(OrderI D 10643) and the beginning of the second order (OrderI D 10692) for the
customer with a Custom erID value of ALFKI. Notice how orders nest within
customers. Also, the line items, or order details, for an order nest within an
order.
Figure 1 2 - 8 . An excerpt from t h e b eginning of t h e XML da t a in t he
m yCustom ersSch em a .xm l file.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Querying D e scendant s in a Da t a Set w it h XPat h
The hierarchical design of the das1 data set in the preceding sample provides a
source that is suitable for dem onstrating how to query descendants with XPath
query syntax. Recall that the data set has order details that are the children of
orders that in turn are the children of customers. In Figure 12-8, the first
UnitPrice value of 45.6 is a descendant of the first order with an Order I D value of
10643. This OrderI D is a child of the custom er with the Custom erI D value ALFKI .
XPath query syntax permits you to create a result set of customers based on any
of their descendant values, such as Unit Price. The sample in this section
illustrates how to construct such an XPath query, and the sample also reveals
how to enumerate the nodes of the result set. Although XPath queries return a
collection of nodes in an Xm lNodeList object, the enum eration reports individual
values without the clutter of the XML tags that delim it values in an XML
document.
The RunXPathQueryForThreeTierXm lDocument procedure, which implements the
sample for this section, starts by instantiating a new data set named das1 and
then populating it with the three-tiered data set created by the
Creat eThreeTierDataSet function. (See the preceding section for the listing with
this function procedure.) Because ADO.NET automatically creates an XML
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
document behind each data set, you can query either the data set or its
underlying XML document and obtain identical result sets.
The RunXPathQueryForThreeTierXm lDocument procedure presents one approach
to processing the XML document behind a data set. After populat ing the data set,
the procedure instantiates a new Xm lDataDocum ent object (xdc1) based on the
das1 data set. The Xm lDat aDocum ent class is an extension of the XmlDocum ent
class that enables .NET applications to load the XML behind a data set into an
XML docum ent. Xm lDataDocum ent objects permit the application W3C processing
techniques for XML docum ents, such as XPath queries. The procedure
dem onstrates this capability by specifying an XPath query that selects all
customer nodes that contain any descendants with a UnitPrice value of more than
100.
The XPath expression creates an Xm lNodeList object (xnl1) based on the
structure of the associated data set for the Xm lDat aDocum ent object that it
queries. The association between the Xm lDataDocum ent object and the das1 data
set m akes it possible to select individual values from each node in the Xm l-
NodeList object as column values in a DataRow obj ect from the DataSet object
model. The procedure prepares to im plem ent this approach by declaring a
Dat aRow object (m yRow). Before starting a loop, the procedure returns a count
of the number of nodes wit hin the xnl1 node list. The loop uses a For Each
statem ent to successively pass through each node within xnl1. The
Get RowFromElem ent method transfers individual values from the current node to
the myRow Dat aRow object. The method transfers values stripped of any XML
tags. Once the values of a node are available as column values within the myRow
object, the procedure constructs a string for the first four column values. The
schema in Figure 12-6 confirms that these columns correspond to Cust omerID,
Com panyNam e, ContactNam e, and Phone. The last statem ent within the loop
prints the four column values to the Output window.
Sub RunXPathQueryForThreeTierXmlDocument()
’Declare and instantiate the das1 data set and
’populate it with the return data set from
’the CreateThreeTierDataSet function procedure.
Dim das1 As New DataSet()
das1 = CreateThreeTierDataSet()
’Declare and instantiate an XmlDataDocument based
’on the contents of das1.
Dim xdc1 As System.Xml.XmlDataDocument = _
New XmlDataDocument(das1)
’Generate a result set with all Customers ordering
’products with a UnitPrice greater than 100.
Dim xnl1 As XmlNodeList = _
xdc1.DocumentElement.SelectNodes( _
"descendant::Customers" & _
"[Orders/OrderDetails/UnitPrice>100]")
’Declare objects for a loop through result set.
Dim myRow As DataRow
Dim xnd1 As XmlNode
Dim str1 As String
’Loop through result set and print values
’in Output window.
Debug.WriteLine("There are " & _
xnl1.Count.ToString & " in the result set.")
For Each xnd1 In xnl1
myRow = xdc1.GetRowFromElement(CType(xnd1, XmlElement))
str1 = myRow(0) & ", " & myRow(1) & _
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
", " & myRow(2) & ", " & myRow(3)
Debug.WriteLine(str1)
Next
End Sub
Figure 12-9 presents an excerpt from the Output window showing values
generated by the RunXPathQueryFor ThreeTierXm lDocument procedure. The first
line in the excerpt reports the number of customers purchasing any item with a
UnitPrice value of m ore than 100. Then the window shows a list of the individual
customers m eeting this criterion. For each customer, the list shows the
associated Cust omerI D, Com panyNam e, Cont actNam e, and Phone values.
Figure 1 2 - 9 . An ex cerpt displaying t he init ial output from t he
Run XPat hQue ryForThr eeTierX m lD ocum e nt pr ocedure.
Querying D e scendant s in a n XM L Docu m ent w ith X Pa t h
The sample in the preceding section created a fresh data set by calling the
Creat eThreeTierDataSet procedure to generate a new data set. For applications in
which the data changes slowly or at regular intervals, you may be able to
improve performance by using a previously saved copy of the XML document
behind a data set. Using a previously saved XML document can reduce the load
on a database server and im prove application responsiveness. The SaveThree-
TierDasAsXm lDocum ent procedure, described previously, saves an XML document
based on the sam e three-tied data structure generated by the
Creat eThreeTierDataSet procedure. The file containing the XML document is
myCust omersSchem a.xml, and its path is c:\ SQLServer Development with
VBDotNet\ Chapter12. I f you updated either the document’s filename or its path
for testing on your system, you will need to revise t hem for the sample in this
section as well.
The sample for this section relies on two procedures. The first procedure,
RunXPathQueryForSavedThreeTierXm lDocument, processes the saved XML
document in myCustomersSchem a.xml. The second procedure, MyTagValue,
extracts tag values from a string containing values delimited by XML tags. The
string values passed to the MyTagValue procedure are the nodes returned from
an XPath query.
The RunXPathQueryForSavedThreeTierXm lDocument procedure starts by
instantiating an XML document, xdc1, and then loading the previously saved
myCust omersSchem a.xml. The procedure uses an Xm lTextReader to connect with
the XML docum ent in myCustomersSchem a.xml, navigate to the root node, and
load the data from the file into xdc1.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
After loading the previously saved XML docum ent, the sample executes the same
XPath query as in the preceding sample. Although the syntax for the XPath query
is identical in this sample and the preceding one, the source for the query is
different in a couple of important ways. First, the source for this sample doesn’t
require a trip to the database server because it works with a locally saved file
containing an XML document. If the database server or the connection to it is
down temporarily, this local resource can substantially improve the robustness of
an application. Second, there is no data set underlying the XML document. This
means the XML nodes returned by the XPath query are strings with no associated
row structure. As a consequence, this procedure processes elements in nodes
differently than in the preceding sample.
This procedure generates identical output to that which appears in Figure 12-9,
but it arrives at that output via a different path than the preceding sample. The
alternative approach to extract ing tag values is necessary because there is no
underlying row structure from a data set to facilitate the extraction of values.
Each node in the XPath query’s result set for this sample is a string. Tags delimit
tag values within each string. From Figure 12-8, you can see that the < Custom er-
I D> and < / Cust om erI D> tags bound the ALFKI tag value. Therefore, you can
extract any tag value by specifying its opening and closing tags. With the Mid
function, you can extract the tag value contained wit hin any tag. The
RunXPathQueryForSavedThreeTierXm lDocument and MyTagValue procedures
work together to extract the first four tag values for each successive node in the
XPath query’s result set. The RunXPathQueryForSavedThreeTierXm lDocument
procedure passes the tag name for each of t he first four tags in a node, and the
MyTagValue function procedure returns a string with the corresponding tag’s
value. Then the RunXPathQueryForSavedThreeTierXm lDocument procedure
concatenates the tag values and writes them to the Output window.
Sub RunXPathQueryForSavedThreeTierXmlDocument()
’Procedure works from saved document instead of
’re-creating the document from a new data set.
’Declare and instantiate an XML document.
Dim xdc1 As New System.Xml.XmlDocument()
’Declare and instantiate reader based on
’previously saved XML document; move to root
’node of document and load into xdc1.
Dim xrd1 As XmlTextReader = _
New XmlTextReader _
("c:\SQL Server Development with VBDotNet\" & _
"Chapter12\myCustomersSchema.xml")
xrd1.MoveToContent()
xdc1.Load(xrd1)
’Close the XmlTextReader.
xrd1.Close()
’Generate a result set with all Customers ordering
’products with a UnitPrice greater than 100.
Dim xnl1 As XmlNodeList = _
xdc1.DocumentElement.SelectNodes( _
"descendant::Customers" & _
"[Orders/OrderDetails/UnitPrice>100]")
’Declare objects for a loop through result set.
Dim xnd1 As XmlNode
Dim str1, str2 As String
’Loop through result set and print values
’in Output window.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
[...]... ees t able on t he dat abase server The sql: field at t r ibut e indicat es t he ser ver - based colum ns t o w hich t he local dat a set colum ns point . cmd1 SqlXmlCommand object
Dim cmd1 As SqlXmlCommand = _
New Microsoft. Data.SqlXml.SqlXmlCommand(cnn1String)
’Designate data source for cmd1 with. topic in the Visual Basic .NET
documentation.) This section in the book includes a couple of samples to
complem ent those from the Visual Basic .NET documentation