Use ADO.NET datasets in Delphi
2008-07-31 20:56
453 查看
Use ADO.NET datasets in Delphi
Abstract: Learn how to use ADO.NET datasets in Delphi, using XML mapper to transform XML across the platforms. Demonstrated using a .NET web service and Delphi client.
//Sys.WebForms.PageRequestManager._initialize('ctl29', document.getElementById('ctl28'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);
//]]>
Introduction
If you've experimented with Web Services, you might have hit some Microsoft .NET based Web Services which return data all right, but it's in the default XML format from ADO.NET. So you end up with some XML but you have no clue what to do with it! This article explains how you can take this XML, make sense out of it and even display it in a DB Grid.
Scope
I'm not going to explain much about .NET, or the ADO.NET XML format. What I'll talk about is the most probable case you'll encounter .NET datasets: as XML returned from a .NET based Web Service. If you're going to use .NET datasets in some other way, you might want to read this article to get an idea of how to make your Delphi application aware of them.
Hitting the .NET service
Let's start with a simple .NET service, as given in http://services.pagedownweb.com/ZipCodes.asmx. I've used the Web Service Importer in File | New | Other | Web Services and generated the Pascal files. Here's the declaration that looks odd:
Using the .NET service in Delphi
I've created a sample form , which looks like this:
Now we've setup the HTTPRio, and the code behind the Get Zip Codes button is:
Interpreting the .NET XML
We have to figure out how to get Delphi to USE this data. We would like to have a Client Data Set read the XML so we can display it all in a Grid. For that we'll have to use XDR transforms. No, that's not very complicated, and here's how we'll do it.
1. First we're going to save the XML returned into an XML file. I've saved it as "data.xml".
2. Run XML mapper from the Tools menu, and open this XML file. Here's a mega screen shot:
3. The ZIPDATA(*) means there's multiple rows of "ZIPDATA" available. Columns availabl are Zip, City, State, County and AreaCode. Let's double-click each one of these to add them to the transformation and then click the DataPacket from XML in the Create Menu. Here's what it all looks like:
4. Save the Transformation using File | Save | Transformation, as "Ziptrans.xtr". Don't try to test the transformation yet. (There's a bug in Delphi Source code that doesn't like SOAP namespaces in certain elements so it doesn't show up any data).
5. We'll now FIX this bug. The XTR file is an XML file which you can open in any text editor. Open it, and change the first line from:
6. We're nearly there. Drop a TClientDataset, a TXMLTransformProvider and a TDatasource on the form. Here's what the form looks like now:
Link the Grid, the Datasource and the ClientDataset, and set the ClientDataset's ProviderName to point to the XML Transform Provider. 7. Set the TransformRead.TransformationFile of the XMLTransformProvider to Ziptrans.XTR.
8. Now we need to set the data of the XML Transform Provider at run time. Here's some additional code in the HTTPRio's OnAfterExecute:
That's it!
Amazing.
Thank you.
What's next?
This transformation is very specific to this particular service and XML schema. SO if you know what XML is going to be returned (the format) then you can use XML mapper to generate a transformation for it.
I haven't been able to write a "general" transform that can be applied to ANY .NET returned XML, but if anyone does I'd love to hear about it.
Also, why have I used the HTTPRio's OnAfterExecute, rather than manipulating the the s_schema parameter? There's another bug in Delphi that doesn't like parameters returned as XML. More revealed in this thread.
You can download all the code for this project at http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=17807 or at http://www.agnisoft.com/soap/dotnetds.zip.
Abstract: Learn how to use ADO.NET datasets in Delphi, using XML mapper to transform XML across the platforms. Demonstrated using a .NET web service and Delphi client.
//Sys.WebForms.PageRequestManager._initialize('ctl29', document.getElementById('ctl28'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);
//]]>
Use ADO.NET Datasets in Delphi
By Deepak ShenoyIntroduction
If you've experimented with Web Services, you might have hit some Microsoft .NET based Web Services which return data all right, but it's in the default XML format from ADO.NET. So you end up with some XML but you have no clue what to do with it! This article explains how you can take this XML, make sense out of it and even display it in a DB Grid.
Scope
I'm not going to explain much about .NET, or the ADO.NET XML format. What I'll talk about is the most probable case you'll encounter .NET datasets: as XML returned from a .NET based Web Service. If you're going to use .NET datasets in some other way, you might want to read this article to get an idea of how to make your Delphi application aware of them.
Hitting the .NET service
Let's start with a simple .NET service, as given in http://services.pagedownweb.com/ZipCodes.asmx. I've used the Web Service Importer in File | New | Other | Web Services and generated the Pascal files. Here's the declaration that looks odd:
rtnZipDSResult = class(TRemotable) private Fs_schema: String; published property s_schema: String read Fs_schema write Fs_schema; end; ZipCodesSoap = interface(IInvokable) ['{FEF279A0-29EE-CF0B-FBB2-7DD79A5502CE}'] ... function rtnZipDS(const City_IN: String; const State_IN: String): rtnZipDSResult; stdcall; ... end;The rtnZipDS function returns a .NET dataset, as XML. Here, the s_schema of the rtnZipDSResult class is simply the dataset as XML in ADO.NET's default format. This means that a .NET client could easily get this XML and show it on a grid or a form - but can we do this with Delphi? Let's see.
Using the .NET service in Delphi
I've created a sample form , which looks like this:
Now we've setup the HTTPRio, and the code behind the Get Zip Codes button is:
procedure TForm1.Button1Click(Sender: TObject); begin (HTTPRIO1 as ZipCodesSoap).rtnZipDS(edtCity.Text, edtState.Text); end;I've also added an event handler on the HTTPRio1.OnAfterExecute like so:
procedure TForm1.HTTPRIO1AfterExecute(const MethodName: String; SOAPResponse: TStream); begin SOAPResponse.Position := 0; Memo1.Lines.LoadFromStream(SOAPResponse); SOAPResponse.Position := 0; end;This is only to display the returned content on to a Memo so we can figure out what to do with it. Here's how the form looks now:
Interpreting the .NET XML
We have to figure out how to get Delphi to USE this data. We would like to have a Client Data Set read the XML so we can display it all in a Grid. For that we'll have to use XDR transforms. No, that's not very complicated, and here's how we'll do it.
1. First we're going to save the XML returned into an XML file. I've saved it as "data.xml".
2. Run XML mapper from the Tools menu, and open this XML file. Here's a mega screen shot:
3. The ZIPDATA(*) means there's multiple rows of "ZIPDATA" available. Columns availabl are Zip, City, State, County and AreaCode. Let's double-click each one of these to add them to the transformation and then click the DataPacket from XML in the Create Menu. Here's what it all looks like:
4. Save the Transformation using File | Save | Transformation, as "Ziptrans.xtr". Don't try to test the transformation yet. (There's a bug in Delphi Source code that doesn't like SOAP namespaces in certain elements so it doesn't show up any data).
5. We'll now FIX this bug. The XTR file is an XML file which you can open in any text editor. Open it, and change the first line from:
<SelectEach dest="DATAPACKETROWDATAROW" from="soap:Envelopesoap:Body...."> [Change To] <SelectEach dest="DATAPACKETROWDATAROW" from="Envelopesoap:Body....">The reason for this is that Delphi's XML Transform provider does not like the "soap:" in the first element of the "from" attribute. That might get fixed in some update pack, so this point might not apply
6. We're nearly there. Drop a TClientDataset, a TXMLTransformProvider and a TDatasource on the form. Here's what the form looks like now:
Link the Grid, the Datasource and the ClientDataset, and set the ClientDataset's ProviderName to point to the XML Transform Provider. 7. Set the TransformRead.TransformationFile of the XMLTransformProvider to Ziptrans.XTR.
8. Now we need to set the data of the XML Transform Provider at run time. Here's some additional code in the HTTPRio's OnAfterExecute:
procedure TForm1.HTTPRIO1AfterExecute(const MethodName: String; SOAPResponse: TStream); var XMLDoc: IXMLDocument; begin SOAPResponse.Position := 0; Memo1.Lines.LoadFromStream(SOAPResponse); ClientDataset1.Active := FALSE; SOAPResponse.Position := 0; XMLDoc := NewXMLDocument; XMLDoc.Encoding := SUTF8; SOAPResponse.Position := 0; XMLDoc.LoadFromStream(SOAPResponse); XMLTransformProvider1.TransformRead.SourceXmlDocument := XMLDoc.GetDOMDocument; ClientDataset1.Active := TRUE; end;You'll notice that we've created an XML Document , loaded it from the Received SOAP stream, and applied the transform to it. The client dataset gets data from the provider and displays the data :
That's it!
Amazing.
Thank you.
What's next?
This transformation is very specific to this particular service and XML schema. SO if you know what XML is going to be returned (the format) then you can use XML mapper to generate a transformation for it.
I haven't been able to write a "general" transform that can be applied to ANY .NET returned XML, but if anyone does I'd love to hear about it.
Also, why have I used the HTTPRio's OnAfterExecute, rather than manipulating the the s_schema parameter? There's another bug in Delphi that doesn't like parameters returned as XML. More revealed in this thread.
You can download all the code for this project at http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=17807 or at http://www.agnisoft.com/soap/dotnetds.zip.
相关文章推荐
- ADO.NET Entity Framework: The version of SQL Server in use does not support datatype 'datetime2'
- Scott doesn't use datasets in ASP .NET Applications
- [转]use wxwidgets and ado in vc.net
- 采用ADO.NET存取Excel数据(Use ADO.NET to Retrieve and Modify Records in an Excel Workbook)
- How To Use ADO.NET to Retrieve and Modify Records in an Excel Workbook With Visual Basic .NET(利用Ado.net导出到Excel)
- Tomcate 启动异常,java.net.BindException: Address already in use: JVM_Bind:80的解决办法
- java.net.BindException: bind failed: EADDRINUSE (Address already in use)
- java.net.BindException: Address already in use: JVM_Bind 解决方法
- Mac OS X:Analysis of the Use of the Boot Server Discovery Protocol in NetBoot
- java.net.BindException: Address already in use: JVM_Bind异常的解决
- ADO.NET Programming in Visual Basic .NET, Second Edition
- Use Typescript in asp.net MVC project.
- java.net.BindException: Address already in use: JVM_Bind:80 异常的解决办法
- CRUD Operations In ASP.NET MVC 5 Using ADO.NET
- 80端口占用异常解决方法java.net.BindException: Address already in use: JVM_Bind:80(或8080)
- DataTable and DataColumn Expressions in ADO.NET - Calculated Columns
- Android中 Address already in use at android.net.LocalSocketImpl.bindLocal
- How to use NSRequest in Delphi XE4
- Use the MachineKey API to protect values in ASP.NET
- ado.net数据操作全接触三(存储过程,datasets)