1. Trang chủ
  2. » Công Nghệ Thông Tin

Beginning Visual Basic .NET Database Programming phần 8 potx

69 237 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 69
Dung lượng 692,07 KB

Nội dung

ADO.NET and XML 25 Relational Data At this point we know how to load and save XML data directly using the DataSet. We also know how to generate schemas and how to use those schemas for validation. However, at this point, we've only seen what happens when we have a single table. As we've already seen in earlier chapters, the DataGrid control is capable of letting us navigate around different tables pretty easily. In this section we'll extend what we have so that, when we have an order shown in the DataGrid, we can drill down to see the lines that make up that order. Try It Out – Relating the "Order Details" Table 1. If the project is running, close it. 2. Using the code editor, find the code for Form1. Make these changes to btnConnect_Click. Private Sub btnConnect_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnConnect.Click ' Connect to the database Dim connection As New sqlconnection(DbString) connection.Open() ' Create a new dataset Dim newDataset As New DataSet("Orders") ' Create a new table to hold the orders in Dim ordersTable As New DataTable("Order") newDataset.Tables.Add(ordersTable) ' Load the last two orders from the database Dim command As New SqlCommand("SELECT TOP 2 OrderID, CustomerID, " & _ "EmployeeID, OrderDate, RequiredDate, ShippedDate, " & _ "ShipVia, Freight, ShipName, ShipAddress, ShipCity, " & _ "ShipRegion, ShipPostalCode, ShipCountry FROM Orders " & _ "ORDER BY OrderID DESC", connection) ' Fill the dataset Dim adapter As New SqlDataAdapter(command) adapter.Fill(ordersTable) ' Create a new table to hold the order details on Dim detailsTable As New DataTable("Detail") newDataset.Tables.Add(detailsTable) ' Form a SQL string so that we only get the details that are ' included in the first table Dim sql As String, row As DataRow For Each row In ordersTable.Rows ' Create a sql snippet If sql <> "" Then sql &= " or " Chapter 12 26 sql &= "OrderID=" & row("orderid") Next ' Do we need to bother? If sql <> "" Then ' Create a new command sql = "SELECT OrderID, ProductID, UnitPrice, Quantity, Discount " & _ "FROM [Order Details] WHERE " & sql Dim detailsCommand As New SqlCommand(sql, connection) ' Fill the new table Dim detailsAdapter As New SqlDataAdapter(detailsCommand) detailsAdapter.Fill(detailsTable) ' Create the new relationship newDataset.Relations.Add("Details", _ ordersTable.Columns("OrderID"), detailsTable.Columns("OrderID")) End If ' Set the dataset property Me.DataSet = newDataset ' Save the schema newDataset.WriteXmlSchema(SchemaFilename) ' Close the database connection.Close() End Sub 3. Run the project and click Connect. You'll be able to use the "plus" buttons to show the Details link. 4. If you click on one of the Details links, you'll be able to see the related data. ADO.NET and XML 27 How It Works None of that should be too new to you, as I'm sure you're comfortable with linking tables with DataRelation objects in this way. (See Chapter 7 for more details.) It's worth taking a quick look at a portion of the code that we added. When we load a list of orders from the database into ordersTable, we need to load corresponding details in detailsTable. The way we do this is by looping through all the rows in ordersTable and creating a SQL snippet. ' Form a SQL string so that we only get the details that are ' included in the first table Dim sql As String, row As DataRow For Each row In ordersTable.Rows ' Create a sql snippet If sql <> "" Then sql &= " or " sql &= "OrderID=" & row("orderid") Next Once we've been through that loop, our sql variable will be set to: OrderID=11077 or OrderID=11076 We can combine this with the larger SQL statement to get this: SELECT OrderID, ProductID, UnitPrice, Quantity, Discount FROM [Order Details] WHERE OrderID=11077 OR OrderID=11076 …and that's precisely what we do next. ' Do we need to bother? If sql <> "" Then ' Create a new command sql = "SELECT OrderID, ProductID, UnitPrice, Quantity, Discount " & _ "FROM [Order Details] WHERE " & sql Dim detailsCommand As New SqlCommand(sql, connection) Chapter 12 28 Once we have the command, we can populate the detailsTable DataTable object as normal: ' Fill the new table Dim detailsAdapter As New SqlDataAdapter(detailsCommand) detailsAdapter.Fill(detailsTable) Finally, we create a relationship so that DataGrid knows how to present the data: ' Create the new relationship newDataset.Relations.Add("Details", _ ordersTable.Columns("OrderID"), detailsTable.Columns("OrderID")) End If Now that we've proven we can load relational data, we need to look at what effect this has on our code to write the XML file. Saving the DataSet Saving the data isn't even worth a "Try It Out…How It Works"! Run the project, click Connect, and then click Save. Save the file with a different name to the one you used before. Now find the file in Windows Explorer and open it. I've omitted quite a bit of XML here for brevity. <Orders> <Order> <OrderID>11077</OrderID> <CustomerID>RATTC</CustomerID> <EmployeeID>1</EmployeeID> <OrderDate>1998-05-06T00:00:00.0000000+01:00</OrderDate> <RequiredDate>1998-06-03T00:00:00.0000000+01:00</RequiredDate> <ShipVia>2</ShipVia> <Freight>8.53</Freight> <ShipName>Rattlesnake Canyon Grocery</ShipName> <ShipAddress>2817 Milton Dr.</ShipAddress> <ShipCity>Albuquerque</ShipCity> <ShipRegion>NM</ShipRegion> <ShipPostalCode>87110</ShipPostalCode> <ShipCountry>USA</ShipCountry> </Order> <Order> … </Order> <Detail> … </Detail> <Detail> … </Detail> <Detail> ADO.NET and XML 29 … </Detail> <Detail> <OrderID>11077</OrderID> <ProductID>2</ProductID> <UnitPrice>19</UnitPrice> <Quantity>24</Quantity> <Discount>0.2</Discount> </Detail> … </Orders> First of all, what's important here is noticing that we don't need to change the code that saves the DataSet as an XML file, even though we've changed the structure of the DataSet. What's also important is that there's no physical link in the XML file between details and orders. It would make sense that the three Detail elements associated with order 11077 actually appeared within the Order element for 11077. But, for now, just bear in mind that we've changed the structure of the DataSet, yet the data can still be written out as XML without any changes. Loading the DataSet Again OK, so when we clicked the Connect button, we made a call to DataSet.WriteXmlSchema and created a new schema. This schema contains the details for the Detail elements and also contains details of the relationship between Order and Detail elements. If you open the OrdersSchema.xml file again, towards the bottom you'll find this: <xsd:element name="Detail"> <xsd:complexType> <xsd:sequence> <xsd:element name="OrderID" type="xsd:int" minOccurs="0" /> <xsd:element name="ProductID" type="xsd:int" minOccurs="0" /> <xsd:element name="UnitPrice" type="xsd:decimal" minOccurs="0" /> <xsd:element name="Quantity" type="xsd:short" minOccurs="0" /> <xsd:element name="Discount" type="xsd:float" minOccurs="0" /> </xsd:sequence> </xsd:complexType> </xsd:element> Again, nothing complex there, we're just defining an element called Detail and specifying the five elements that it contains. Notice that Detail and Order appear as sibling elements in the document – they're at the same level. They'll appear as siblings to each other in the final XML document too. Chapter 12 30 Beneath, you'll see this: <xsd:unique name="Constraint1"> <xsd:selector xpath=".//Order" /> <xsd:field xpath="OrderID" /> </xsd:unique> This block is used to create a constraint, specifically one called Constraint1 that's used to specify that the OrderID element contained within the Order element is unique. Finally, you'll see this: <xsd:keyref name="Details" refer="Constraint1"> <xsd:selector xpath=".//Detail" /> <xsd:field xpath="OrderID" /> </xsd:keyref> What this tells us is that we have a relationship called Details that links Constraint1 to the OrderID element within Detail elements. By definition, Constraint1 refers to the OrderID element within Order elements and therefore we know that the OrderID in Order links to the OrderID in Detail. Now, run the project and click Connect and then Load. You'll see this: The trick here is that we've continued to use ReadXmlSchema as soon as the new DataSet is created. (I've omitted code here for brevity.) Private Sub btnLoad_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnLoad.Click ' Display the dialog dlgOpenFile.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*||" If dlgOpenFile.ShowDialog() = DialogResult.OK Then ' Try and load Try ' Create a new dataset Dim newDataset As New DataSet() ADO.NET and XML 31 ' Load the schema newDataset.ReadXmlSchema(SchemaFilename) ' Create a validating reader … ' If we got here, we can load it Me.DataSet = newDataset Catch ex As Exception … End Try End If End Sub Because the schema contains details on the relationship between Orders and Order Details, when the data is loaded from XML, the relationship "sticks" and the DataGrid is able to present the information properly. Remember, because we've created a new OrdersSchema.xml file, you won't be able to load the old XML files that don't contain Detail elements. XmlDataDocument The last important class that we need to look at with respect to using XML with DataSets is System.Xml.XmlDataDocument. XmlDataDocument "wraps" a DataSet but maintains a continuous connection between the document and the Dataset. This means that changes to the XML document are instantly reflected in the DataSet and changes to the DataSet are instantly reflected in the XML document. In this section, we'll take a look at a couple of ways in which this object can be used. Changing the XML Changes the DataSet For this exercise, we'll imagine that we've been given an XML document that contains an order from a customer. However, we'll say that we've recently made some changes to our product portfolio and we're going to substitute some product IDs with other product IDs. What we'll do is go through the XML document element by element and do a search and replace. In order to get this example working, you're going to have to look at the data stored in your copy of NorthwindSQL. We need to find a product ID. Chapter 12 32 Try It Out – Finding a Product ID 1. Run the project and click either the Connect or Load button to get some data. 2. Of the two orders you have, choose one. (I've chosen one with the least amount of detail rows associated with it.) Expand the details. 3. Look through the details and choose a product ID that appears in the details list. I've chosen 14 but, as I say, you'll need to choose one that appears in your list. 4. Note down the product ID. You'll need it in a moment. Making Changes Now that you have a product ID, you can start writing code! Try It Out – Changing Data in an XmlDataDocument 1. If the project is running, close it. 2. Using Solution Explorer, right click on the Order Export project and select Add | Add Class. Call the new class DataReplace. 3. When the code editor for DataReplace is opened, add this code: Public Class DataReplace ' Members Public ElementName As String Public LookFor As String Public ReplaceWith As String End Class 4. Again, using Solution Explorer, create a new class called DataReplaceCollection. Add this code: Public Class DataReplaceCollection Inherits CollectionBase Chapter 12 34 9. Double-click on the Replace button to create a new Click event handler. Add this code: Private Sub btnReplace_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnReplace.Click ' Create a collection Dim replaceCollection As New DataReplaceCollection() ' What do we want to replace? Dim replace As New DataReplace() replace.ElementName = "ProductID" replace.LookFor = 14 replace.ReplaceWith = 999 replaceCollection.Add(replace) ' Do the replace ReplaceData(replaceCollection) End Sub 10. In the above code sample, remember to replace this line: replace.LookFor = 14 …with whatever product ID you noted down before. 11. Then, add this method: Public Sub ReplaceData(ByVal replaceCollection As DataReplaceCollection) ' Turn off checking Dim enforce As Boolean = DataSet.EnforceConstraints DataSet.EnforceConstraints = False ' Run the replace DoReplace(replaceCollection, Document.FirstChild) ' Reset checking DataSet.EnforceConstraints = enforce End Sub [...]... ProductsDataSet.vb and a ProductsDataSet.xsx file If you open the code in ProductsDataSet.vb, you will see that it contains Visual Basic NET code defining each element in the schema ProductsDataSet.xsx is a file used by Visual Studio to determine information about how to display the schema in the designer 9 48 In the Solution Explorer, double click on the entry for the XML schema you just added You will see a screen... not only improves the readability of your code, but also enables Visual Studio NET's IntelliSense feature to make context-sensitive suggestions as you type in code You can think of this as a way to early bind to your DataSet, as opposed to the late binding that occurs with non-typed DataSets Early binding is the ability to make Visual Basic NET aware of the exact type of an object at design time, whereas... examined the System.Xml.XmlDataDocument class This is a useful class that allows manipulation of the same basic data either through a DataSet object or through the XmlDataDocument itself Finally, we took a very quick look at typed DataSets That brings us to the end of our discussion on the basics of how ADO.NET can expose XML data to us and how we can manipulate that data In the next chapter, we'll learn... time being 8 Now, click the Invoke button and a new Internet Explorer window will appear containing the XML document as shown: How It Works Back in Chapter 11, when we looked at ASP.NET, one subject that came up was that of "code behind" When an application uses code behind, each page on the web server is associated with a code file containing the classes for building that page In normal ASP.NET projects,... 2 In Visual Studio NET, we can use this file to generate a typed DataSet, based on the type information it details Start a completely new Windows Application project for this quick example Then select Project | Add Existing Item 3 In the Add Existing Item dialog box, browse to find the ProductsDataSet.xsd schema and open it 47 Chapter 12 4 5 Notice how Visual Studio NET takes the... 12 4 5 Notice how Visual Studio NET takes the XSD schema and renders it visually on screen If you want to see the file in its original XML format, just click on the XML tab at the bottom 6 Select Schema from the menu and then choose Generate DataSet 7 Click the Show All Files button in Solution Explorer to make all files visible 8 If you expand the ProductsDataSet.xsd branch by clicking on the plus... element, we go through each of the DataReplace objects comparing the values, looking for one whose ElementName property matches the Name property of the node (And in our case we're looking for ProductID.) 38 ADO.NET and XML ' Do we have an element? If node.NodeType = XmlNodeType.Element Then ' Go through each one Dim replace As DataReplace For Each replace In replaceCollection ' Does name match? If replace.ElementName... node.NextSibling Loop End Sub 8 That's all we need to do in order to create a form that lets us view the current contents of an XmlDataDocument object 9 Open the code editor for Form1 Add this member: Public Class Form1 Inherits System.Windows.Forms.Form ' Members Private _dataset As DataSet Private _document As XmlDataDocument Private _documentView As XmlDocumentView 42 ADO.NET and XML 10 Flip over to... computer and operating system they may be using Try It Out – Building a Web Service 1 We can use a wizard to create a Web Service project for us Open Visual Studio NET and select New | Project from the menu 2 From the Templates list on the right, select ASP.NET Web Service Enter the name of the project as NorthwindWebService, and click OK: 3 Chapter 13 Try not to enter spaces or other odd characters into... ' Bind datagridOrders.DataSource = _dataset datagridOrders.DataMember = _dataset.Tables(0).TableName ' Create the document _document = New XmlDataDocument(_dataset) End Set End Property 36 ADO.NET and XML Basically, when we want to replace data, we can take one of two approaches We could walk through each row of each table defined in the DataSet looking for columns with a particular name, comparing . <OrderDate>19 98- 05-06T00:00:00.0000000+01:00</OrderDate> <RequiredDate>19 98- 06-03T00:00:00.0000000+01:00</RequiredDate> <ShipVia>2</ShipVia> <Freight> ;8. 53</Freight> . Grocery</ShipName> <ShipAddress> 281 7 Milton Dr.</ShipAddress> <ShipCity>Albuquerque</ShipCity> <ShipRegion>NM</ShipRegion> <ShipPostalCode> ;87 110</ShipPostalCode> . Create the document _document = New XmlDataDocument(_dataset) End Set End Property ADO .NET and XML 37 Basically, when we want to replace data, we can take one of two approaches. We could walk

Ngày đăng: 13/08/2014, 12:21