Web と Web サービス経由で SQL Server 2000 および Reporting Services と XML を交換する
Venkat Prasad
Microsoft Corporation
January 2005
日本語版最終更新日 : 2005 年 3 月 29 日
適用対象:
Microsoft SQL Server 2000
XML Web サービス
要約: Microsoft SQL Server、Web サーバー、XML Web サービス、および Microsoft SQL Reporting Services からの XML データを保存するためのプログラミング技法をいくつか説明します。このトピックでは、XML ストリームを保存するために従来から使用されている技法と新しい技法が比較されています。従来の技法は、ASP/ASPX と COM を使用するものです。新しい技法には、.NET Framework クラス (データセット、XMLTextReaders と XMLTextWriters、XSLTransformation) を使用した SQL Reporting Services からのデータの保存、および SQL Server への XML のアップロードがあります。この記事には英語のページへのリンクも含まれています。
目次
はじめに
ASP と ASPX、COM、および URL アクセスを使用して Web から XML をダウンロードする
XML Web サービスから XML データをダウンロードする
SQL Reporting Service から XML データをダウンロードする
XML データを SQL Server 2000 にアップロードする
まとめ
はじめに
最近では、ビジネス データがインターネットやイントラネット上に公開されることがますます増えてきました。ビジネス データは、従来からの Web サーバー呼び出し (HTTP POST)、.NET XML Web サービス、さらには Microsoft SQL Reporting Services を使って回線上を XML として移動しています。従来の Web サーバー呼び出し (HTTP POST) からのデータとは異なり、XML Web サービスや SQL Reporting Services からのデータは、SOAP プロトコルを使って異なるプラットフォームからアクセスすることもできます。
多くの SQL 開発者は、さまざまな Web ソースによって公開される大量の XML データを SQL Server から取り出すツールを作成するという課題に取り組んでいます。さまざまな形式の XML データを処理および変換することや、異なるデータ コンシューマが必要とする形式に変換することがこの課題をますます困難にしています。
従来からの方法: 従来の Web サーバー呼び出し (HTTP POST) では、SQL Server からの XML データが、"FOR XML" 句を含む ADODB ストリームを使用して、ASP と ASPX、および COM により公開されます。コーディングを希望しない場合は、ブラウザにデータを表示する別の一般的な方法として、仮想ディレクトリを設定することによる "URL アクセス" があります (この場合、Microsoft SQL Server 2000 に同梱されている IIS ユーティリティで SQL XML サポートを構成する必要があります)。ストリームの保存だけが目的で、ブラウザにはデータを表示しない場合は Web サーバーは不要です。この場合、COM を Visual Basic スクリプトにラップすることができます。さらに、テンプレート ファイル、XSL (Extensible Style Sheet)、XPath クエリを適用したり、リレーショナル スキーマへのマッピング ファイルを使用することで、XML ストリームをカスタマイズします。ActiveX Data Objects (ADO) データ モデル (レコードセットと ADO ストリーム) は、Microsoft .NET Framework (ADO.NET データセット クラスとフレームワーク クラス) のデータ モデルとは異なることに注意してください。COM の型やバージョン管理に関する問題点もありますが、データに汎用的にアクセスできず、プラットフォームにも依存します。
.NET と XML Web サービス: .NET では、ADO.NET データセット、または XmlTextReader クラスと XmlTextWriter クラスのいずれかを使用して、("FOR XML" 句により) SQL Server からの XML ストリームを保存できます。たとえば、HTML の表示形式を整えるため、または XML ドキュメントの形状や形式を変更するために XSL 変換を適用できます。これらは、Web サーバーを経由しないで、C# や Visual Basic .NET クライアントから呼び出すことができます。しかし、さらに優れている点は、これらのメソッド呼び出しをインターネット上に XML Web サービス メソッドとして適切に公開できることです。つまり、プラットフォームに依存しない、SOAP プロトコルによるユニバーサル データ アクセスになります。
この記事では、従来からのアプローチと .NET アプローチの両方を取り上げます。Reporting Services では、独自のレポートが XML Web サービス メソッドによって公開されるので、記事を完全にするために SQL Reporting Services から XML データをダウンロードする方法も説明します。最後に、XMLBULKLOAD ユーティリティを使用して XML を SQL Server にアップロードする方法について説明します。
ASP と ASPX、COM、および URL アクセスを使用して Web から XML をダウンロードする
従来の方法で SQL Server から XML データを公開するときは、ASP ページまたは ASPX ページで ADODB ストリーミング メソッドを、直接または COM コンポーネント経由で使用します。このとき、結果を XML ストリームとして返すために "For XML" 句を指定する必要があります。COM コンポーネント経由で公開する場合でも、IIS サーバーが専用の SQL Server に存在する必要はありません。この技法では、クライアントからは、クエリ文字列を使ってクエリ パラメータを渡し、HTTP POST または HTTP GET を使用してデータにアクセスできます。
注: この記事では ASP または ASPX 経由で COM を使用していますが、COM を使用せずにプレーンな ASP または ASPX を使用して同じコードを記述できます。
以下で示した Web.asp を C# クライアントから呼び出します。ASP ページでは、HTTP POST によって渡された SQL クエリを使用する Visual Basic COM オブジェクトのインスタンスが作成されます。その後、XML ストリームが取得され、そのストリームが XML ドキュメントとして UNC 共有またはファイル パスに保存されます。現実には、Web 要求から送信されたランダムな SQL クエリを実行することは非常に危険ですが、ここではこのアプローチを使用して、要求から入力データを受け取る概念を説明します (実際には、受信データを検証してから SQL クエリの作成に使用することをお勧めします)。ASPX ページの呼び出しにも同じ技法が使用されます。互換性を維持するために、ASPX ページを一部変更する必要があることに注意してください。set ディレクティブを削除し、"応答" と "メソッド " をかっこで囲んで、<% @Page Explicit="True" aspcompat="true" %> を追加する必要があります。これをテストする場合は、ASP ページと ASPX ページの両方を同じ IIS 6.0 サーバーで実行できます。
サンプルの Visual Basic COM オブジェクトには、ConnectToSQLServer と ExecuteForXMLSQL の 2 つのメソッドがあります (このオブジェクトは "Program Files\Common Files\System\ado\msador15.dll" を参照します)。このコードを ActiveX.dll としてコンパイルし、"adodbStream.dll" という名前を付けました。
Public Function ConnectToSQLServer(ByVal SrvName As String,
Optional ByVal DbName As String = "master", Optional ByVal UsrName As String,
Optional ByVal Passwd as String)
Set cn = New ADODB.Connection
cn.ConnectionTimeout = 0
cn.Provider = "sqloledb"
cn.Properties("Data Source").Value = SrvName
cn.Properties("Initial Catalog").Value = DatabaseName
cn.Properties("Integrated Security").Value = "SSPI"
cn.Open
End Function
Public Function ExecuteForXMLSQL (ByVal MySQLQuery As String,
Optional ByVal isXML As Boolean, Optional ByVal strFileSavePath As String)
Dim mystr1, mystr2 As String
Dim objStream, adostreamquery As ADODB.Stream
On Error GoTo ErrorTrap:
cn.CursorLocation = adUseServer
Set cmd = New ADODB.Command
cmd.ActiveConnection = cn.ConnectionString
cmd.CommandType = adCmdText
Set adostreamquery = New ADODB.Stream
adostreamquery.Open
adostreamquery.WriteText <?xml version="1.0" standalone="yes" ?>
adostreamquery.WriteText "<ROOT xmlns:sql='urn:schemas-microsoft- com:xml-sql'> ",
adWriteChar
adostreamquery.WriteText " <sql:query> ", adWriteChar
adostreamquery.WriteText MySQL, adWriteChar
adostreamquery.WriteText " </sql:query> ", adWriteChar
adostreamquery.WriteText "</ROOT> ", adWriteChar
adostreamquery.Position = 0
Set cmd.CommandStream = adostreamquery
''' XPATH コマンドの場合は、次の Dialect が異なります。
cmd.Dialect = "{5D531CB2-E6Ed-11D2-B252-00C04F681B71}"
Set objStream = New ADODB.Stream
objStream.Open
cmd.Properties("Output Stream") = objStream
cmd.Execute , , adExecuteStream
objStream.Position = 0
objStream.SaveToFile strFileSavePath, adSaveCreateOverWrite
ExecuteForXMLSQL = "File Saved at Share :" & strFileSavePath
End Function
"FOR XML" によって SQL Server から返されるストリームは、ルート ノードのないドキュメント フラグメントです。SQL ストリームを XML ドキュメントとして保存するには、次のようなコードを追加する必要があります。
adostreamquery.WriteText "<ROOT xmlns: sql='urn: schemas-microsoft- com: xml-sql'> ", adWriteChar
代わりに、ADO コマンド オブジェクトの XML Root プロパティを使用するか、ADO コードでテンプレート ファイルを指定できます。
次のサンプル Web.asp ページは、上記の COM オブジェクトによって公開されるメソッドを使用する ASP ページです。
<%@ LANGUAGE="VBScript" %>
<% Option Explicit %>
<script LANGUAGE="VBScript" runat = server>
</script><%
Dim myobject, Mystring, MySQLQuery, strTableName, strColName, strTopNumRecords,
strSavePath
strTableName = Trim(request.QueryString("TableName"))
strColName = Trim(request.QueryString("ColName"))
strTopNumRecords = Trim(request.QueryString("TopNumRecords"))
strSavePath = Trim(request.QueryString("SavePath"))
set myobject = server.CreateObject("adodata.server")
myobject.Connect "MySQLServer", "MyDatabaseName"
MySQLQuery= "select TOP " & strTopNumRecords & " " & strColName & " from " &
strTableName & "(nolock) FOR XML AUTO"
Mystring =myobject.ExecuteSQL(MySQLQuery,"true",strSavePath)
set myobject = nothing %>
注: 原則的に、実際のアプリケーションでは、SQL インジェクション攻撃に対して脆弱になるので、Web URL を使用して直接クエリを渡してはいけません。ロジックをテンプレート (次のセクションで説明) またはストアド プロシージャにカプセル化することをお勧めします。また、プランがキャッシュされ、コードがプリコンパイルされるので、ストアド プロシージャを使用して GROUP-BY 句を含む XML の階層ビューを作成するために、"FOR XML EXPLICIT" を使用することもお勧めします。
この Web.asp ページは、(ブラウザから HTTP POST を呼び出すのと同様に) Web クライアント クラスまたは HttpWebRequest クラスを使用して C# クライアントから呼び出すことができます。次の C# クライアントでこのページを呼び出します。
public bool GetDataFromASPXWebPage(string SourceUrl,
string Savepath){// 新しい 'HttpWebRequest' オブジェクトを作成します
try{
HttpWebRequest myHttpWebRequest=
(HttpWebRequest)WebRequest.Create(SourceUrl);
// HttpWebRequest の 'Timeout' プロパティを設定します
myHttpWebRequest.Timeout=1000;
myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();
Stream response = myHttpWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
// ストリームをストリーム リーダーにパイプ出力します
StreamReader readStream = new StreamReader( response, encode );
Console.WriteLine(readStream.ReadToEnd());
readStream.Close();
return true;}
catch (Exception e)
{Console.WriteLine("{0} 例外がキャッチされました。", e);
Console.WriteLine("{0} 例外がキャッチされました。", e.Message);}
return false;}
// 次のコードを使用して、上記の c# メソッドが呼び出されます
string URL="http://WebServer/Web.asp?TableName=mytblname&ColName=myColumnname
&TopNumRecords=1000&SavePath=\\\\RemoteServer\\XML\\WebXMLData.xml";
try{NewSourceSavePath = SourceSavePath + "\\" + "WebXMLData.xml";
T0 = System.DateTime.Now;
if(GetDataFromASPXWebPage (URL,NewSourceSavePath))
{T1 = System.DateTime.Now;
Console.WriteLine("\nWebClient ポストの所要時間 :{0}" ,diff1 = T1.Subtract(T0)); }}
catch (Exception e){
Console.WriteLine("{0} Exception caught.", e);}
また、HTTPWebRequest を使用する代わりに、Web ページにポストするための WebClient クラスを使用できます。パラメータを渡すには、NameValueCollection クラスを次のように使用できます。
WebClient wc=new WebClient();
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
wc.Credentials=CredentialCache.DefaultCredentials;
System.Collections.Specialized.NameValueCollection SNS = new
System.Collections.Specialized.NameValueCollection();
SNS.Add("TableName","tblnetstatsperds");
SNS.Add("ColName","ns_client");
SNS.Add("TopNumRecords","1000000");
SNS.Add("SavePath",@"c:\\xmltest\mytest.xml");
wc.QueryString =(SNS);
String postData= "";
// バイト配列として文字列を取得するために ASCII エンコーディングを適用します
Byte[] byteArray =System.Text.Encoding.ASCII.GetBytes(postData);
try{
Byte[] res=wc.UploadData(SourceUrl,"POST",byteArray);
String XmlFrag=System.Text.Encoding.ASCII.GetString(res);
XmlDocument mydoc=new XmlDocument();
mydoc.LoadXml(XmlFrag);
mydoc.Save(Savepath);
return true;}
注: Web.asp ページは、ファイルが C# クライアントに正常に保存されたという状態を返すだけです。この例では、ブラウザにストリームを表示するのではなく、ストリームを XML ドキュメントとして保存しました。ブラウザに XML を表示する場合は、Web.asp に response.write タグを追加し、Visual Basic COM オブジェクト メソッド (ExecuteForXMLSQL) のコードを変更して、ADODB.Stream を返し、直接ファイルに保存しないようにします。
URL アクセスは、SQL Server のデータを主にブラウザで公開するもう 1 つの方法です。これは、SQL Server 2000 に同梱されている "IIS での SQL XML サポートの設定" ユーティリティを使用して実行します。Sqlisapi.dll は、ネイティブの OLE DB Provider for SQL Server (SQLOLEDB) を使用して、仮想ルートで識別される Microsoft SQL Server のインスタンスと通信します (XML 機能は Sqlxmlx.dll に実装されます)。テンプレート ファイル、XML-Data Reduced (XDR) スキーマ ファイル、および Extensible Stylesheet Language (XSL) ファイルは、IIS サーバー上に常駐します (これらのファイルが SQL Server 上になくても問題ありません)。仮想ディレクトリと仮想名を構成 (Template、Schema、dbobject の 3 種類が有効です) してから、次のセクションで示すように URL 呼び出しを使用して、データをブラウザに表示できます。
テンプレート: XSL、XPATH、および XDR
テンプレートとは、1 つ以上の SQL クエリで構成される、有効な XML ドキュメントです。URL では、次のようにテンプレート名を指定できます。
http://WebServer/VirtualDirecotoryName/TemplateVirtualName/MyTemplatefile.xml。ここで指定する "MyTemplatefile.xml" 内に SQL クエリを含めることができます (この資料の例では、SQL Server 2000 同梱の NorthWind サンプル データベースを参照します)。
<root xmlns:sql="urn:schemas-microsoft-com:xml-sql" >
<sql:query>
SELECT 1 as Tag, NULL as Parent,Customers.city as [CITY!1!city],
Customers.ContactTitle as [CITY!1!ContactTitle],
Customers.ContactName as [CITY!1!ContactName]
FROM Customers
GROUP BY city,ContactName,ContactTitle
FOR XML EXPLICIT
</sql:query>
</root>
また、テンプレートに有効な Extensible Style Sheet Language (XSL) を指定することもできます。たとえば、上記の結果をさらにカスタマイズします。得意先名で並べ替えたり、得意先の部署列を非表示にしたり、顧客名を属性ではなく要素として表示したりします。この操作を行うには、上記で指定したテンプレートに次の XSL スタイル シートを適用します (MyTemplatefile.xml の先頭行に sql:xsl="MyXsl.xsl"> を追加します)。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<root>
<xsl:for-each select="root/CITY" order-by="+@ContactName">
<City>
<xsl:attribute name="CityName"><xsl:value-of select="@city"/></xsl:attribute>
<xsl:element name="CustomerName"><xsl:value-of select="@ContactName"/></xsl:element>
</City>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
テンプレートに XPath クエリを記述し、パラメータとマッピング スキーマを定義できます。注釈付きのマッピング スキーマまたは XDR ファイルは、リレーショナル データベースのテーブルと列に XML 要素や属性をマッピングするように定義できます。概念的には、XDR (XML-Data Reduced) スキーマは、(SQL ビューの作成やビューのクエリと同様に) XPath クエリを適用できる XML ビューです。マッピング ファイルでは、ビューの定義と同様に列名とデータ型を定義します (既定では、注釈付きスキーマ内の要素名は、指定されたデータベースのテーブル (またはビュー) 名にマッピングされ、属性名は列名にマッピングされます)。このようなマッピング スキーマがテンプレートを指し (<sql:xpath-query mapping-schema="MyView.xdr">)、パラメータを含めることができます。たとえば、MyXdr ファイルを指すテンプレートを定義する場合は、次のようになります。
<root xmlns:sql="urn:schemas-microsoft-com:xml-sql" >
<sql:xpath-query mapping-schema=" MyView.xdr">
/CUSTOMER
</sql:xpath-query>
</root>
ここで、MyView.xdr は属性から列へのマッピングを定義します。また、次のように、CUSTOMER は要素、ID と name は属性になります。
<?xml version="1.0" ?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data" xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<ElementType name="CUSTOMER" sql:relation="MyCustomers">
<!-- 列にマップされる XML の属性-->
<AttributeType name="ID" />
<AttributeType name="name" />
<!-SQL テーブルのビュー列の定義 -->
<attribute type="ID" sql:field="CustomerID" />
<attribute type="name" sql:field="CompanyName" />
</ElementType>
</Schema>
URL クエリ アクセス (IIS サーバー) を使用する例を除けば、これらすべての例ではストリームを XML ドキュメントとして保存するために、クライアント側から適切な構文、マッピング スキーマ参照、ADO のコマンド オブジェクトの基本パスのプロパティを指定して ADO コードを使用できます。
XML Web サービスから XML データをダウンロードする
XML Web サービスでは、Web メソッドを指定してデータを公開します。このデータは、SOAP メッセージングを使用してどこからでもアクセスでき、ASP や ASPX とは異なり、プラットフォームには依存しません。ここでは、2 つの Web メソッドについて説明します。1 つは、("FOR XML" を指定する) データセットを使用するメソッド、もう 1 つは XmlReaders を使用するメソッドです (XML Web サービスでデータを表示しない場合は、C# クライアント コードでプレーンなメソッドとして、同じコードを使用できます)。
[WebMethod]
public GetXMLDataStreamDS(string SQLQuery,string SavepathWithFileName)
{ // XmlTextReader クラスが "FOR XML" を使用するストリームを取得します
string Myconnetionstring = "Trusted_Connection=Yes;" + "initial catalog=MyDatabase;"
+ "data source=MyServerName";
SqlConnection SQLConn = new SqlConnection(Myconnetionstring);
SqlCommand selectCMD = new SqlCommand(SQLQuery, SQLConn);
selectCMD.CommandTimeout = 0;
SQLConn.Open();
DataSet myDataSet = new DataSet();
XmlTextReader Xrdr = (XmlTextReader)selectCMD.ExecuteXmlReader();
try{
myDataSet.ReadXml(Xrdr, XmlReadMode.Fragment);
myDataSet.WriteXml(SavepathWithFileName,XmlWriteMode.IgnoreSchema);}
catch(Exception ex){
throw new ApplicationException("エラー: " + ex.Message, ex);}
finally{SQLConn.Close();
Xrdr.Close();}
データセットでは、非接続のデータ キャッシュがサポートされます。さらに、XML シリアル化、XML スキーマの読み取りと書き込み、XML としてのリレーショナル データの書き込みなどの機能のサポートが含まれます。ただし、データセット全体をメモリに読み込む必要があるので、コンピュータに十分なメモリがあることを確認してください (これは、インメモリ表現の ADO RecordSet に似ています)。次のように、データセットを XmlTextWriter や XSLTransform と併用して、ストリームを XML ドキュメントとして保存できることにも注意してください。
DA.Fill(myDataSet);
XmlTextWriter xmlw = new XmlTextWriter(SavepathWithFileName, System.Text.Encoding.UTF8);
xmlw.WriteStartElement("ROOT");
xmlw.WriteComment("これは MSDN のサンプルです");
XPathDocument doc = new XPathDocument(new System.IO.StringReader(myDataSet.GetXml()));
System.Xml.Xsl.XslTransform xslt = new System.Xml.Xsl.XslTransform();
xslt.Load(@"c:\xmltest\mySchema.xslt");
xslt.Transform(doc, null, xmlw,null);
xmlw.Flush();
xmlw.Close();}
catch(Exception ex)
{throw new ApplicationException("エラー: " + ex.Message, ex);}
finally{SQLConn.Close();} }
XmlReader クラスなどのストリーミング API クラスでは、キャッシュされない、前方のみの読み取り専用アクセスが提供されます。これにより、柔軟性とパフォーマンスが向上し、データセットと比較するとメモリ使用量が少なくなります。また、データセットと同様に、ストリーミング API クラスを使用する場合でも、XslTransform を適用し、XPath やフィルタを使用して、ノードをさらに操作したり、対象以外のノード セットをスキップすることができます (つまり、While XmlReader.Read() メソッドを使用できます)。ビジネス アプリケーションで必要な場合は、XPathNavigator クラスを使用します。
次の例では、XmlTextReader クラスを使用してコマンド オブジェクトの ExecuteXmlReader メソッドが返した "FOR XML" ストリームを取得し、XmlTextWriter のインスタンスを作成して、"ROOT" 要素を書き込みます (または適切な XSLT を使用することもできます)。その後、XPath ドキュメントのコンストラクタ引数 XSLTransform に XmlReader を渡すか、またはデータを XML ドキュメントとして保存する前に XPath を適用します。
[WebMethod]
public GetXMLStreamNoDataset(string SQLQuery,string SavepathWithFileName){
string Myconnetionstring = "Trusted_Connection=Yes;" + "initial catalog=MyDatabase;"
+ "data source=MyServerName";
SqlConnection SQLConn = new SqlConnection(Myconnetionstring);
SqlCommand selectCMD = new SqlCommand(SQLQuery, SQLConn);
XmlTextWriter xmlw = new XmlTextWriter(SavepathWithFileName, System.Text.Encoding.UTF8);
try{selectCMD.CommandTimeout = 0;
SQLConn.Open();
XmlTextReader txtrdr= (XmlTextReader)selectCMD.ExecuteXmlReader( );
xmlw.WriteStartElement("ROOT");
xmlw.WriteComment("これは Venkat によるサンプルです");
XPathDocument doc = new XPathDocument(txtrdr, XmlSpace.Default);
System.Xml.Xsl.XslTransform xslt = new System.Xml.Xsl.XslTransform();
xslt.Load(@"c:\xmltest\mySchema.xslt");
xslt.Transform(doc, null, xmlw,null);
xmlw.Flush();}
catch (Exception ex){throw new ApplicationException
("エラー: " + ex.Message, ex); }
finally{ SQLConn.Close();
xmlw.Close();} }
これらの XML Web サービス メソッドは、C# クライアント コードから (この例と同様に、Visual Studio で生成された) プロキシ クラスおよび Web 参照を使用して呼び出します。
public bool GetWebServiceXMLDataDS (string SQLQuery, string FilenameWithSavePath){
try{StreamingApp.venkat.MyXMLWebClass MywebObj = new MyXMLWebClass();
MywebObj.Timeout = 1000;
bool Success = MywebObj.GetXMLDataDS(SQLQuery,FilenameWithSavePath);
if (Success){
Console.WriteLine("ファイルは次のパスに正常に書き込まれました: {0}",FilenameWithSavePath);}
return true; }
catch (Exception e) {
Console.WriteLine("{0} 例外がキャッチされました。", e);
Console.WriteLine("{0} 例外がキャッチされました。", e.Message);}
return false; }
public GetWebServiceXMLDataStream(string SQLQuery, string FilenameWithSavePath){
try{StreamingApp.venkat.MyXMLWebClass MywebObj = new MyXMLWebClass();
MywebObj.Timeout = 1000;
bool Success =MywebObj.GetXMLStreamNoDataset(SQLQuery,FilenameWithSavePath);
if (Success){Console.WriteLine("ファイルは次のパスに正常に書き込まれました: {0}",FilenameWithSavePath);}return true;}
catch (Exception e){
Console.WriteLine("{0} 例外がキャッチされました。", e);
Console.WriteLine("{0} 例外がキャッチされました。", e.Message);}
return false;}
//クライアント コード内でのメソッド呼び出し時間を計測します
try{ T0 = System.DateTime.Now;
if(sc. GetWebServiceXMLDataDS ("select TOP 1000 myColumname from myTableName(nolock)
FOR XML AUTO, XMLDATA ",SourceSavePath + "XMLWebServiceDataStream.xml")){T1 = System.DateTime.Now;
Console.WriteLine("\nWebServiceXMLDataStream の所要時間:{0}",diff1 = T1.Subtract(T0));}}
catch (Exception e)
{Console.WriteLine("{0} 例外がキャッチされました。", e); }
注: XML ファイルを保存する上記の Web サービス メソッドの例は、説明目的だけで使用されています。実際には、Web サービスは XML を返すように作成されます。また、ストリームを DOM に読み込み、その DOM を返すこともできますが、おそらく、データセットを取得して XmlDomDocument を関連付ける方がうまくいきます。
Microsoft SQL Server 2000 を Web サービスとしてクライアント側に公開する、Web サービス ユーティリティ キット (SQLXML) もダウンロードできます。SQLXML を実行しているサーバーに Web サービス要求を送信できます。これについては、この記事では説明していません。詳細については、「Web Services (SOAP) Support in SQLXML」を参照してください。
SQL Reporting Services から XML データをダウンロードする
XML Web サービスと同様に、SQL Reporting Services のデータは、SOAP メッセージングを使用してどこからでもアクセスできます。つまり、ASP や ASPX (HTTP POST) を使用した従来の Web サーバー呼び出しで公開されるデータとは異なり、プラットフォームに依存しません。C# クライアントを使用すると、レポートからのコード データを XML ファイルとしてダウンロードできます。つまり、グラフとチャートの MHTML や .CSV ファイルのような、他の形式をサポートできます。実際には、レポート定義もダウンロードできます。実際のレポートは *.rdl ファイルですが、XML ファイルなのでメモ帳で開くことができます。そのため、簡単にカスタマイズや再配置ができます。次のサンプル コードでは、SQL Reporting サーバーからデータをダウンロードし、そのデータを共有に保存する方法を示しています。これは、上記で説明した WebClient クラスの使用例と似ています。
public bool GetSQLReportingServerData(string Savepath, string Filename)
{string Savepathfilename = Savepath + Filename;
try{
StreamingApp. MyReportServer.ReportingService MywebReportServer =
new StreamingApp.MyReportServer.ReportingService();
MywebReportServer.Credentials = System.NET.CredentialCache.DefaultCredentials;
// 引数を設定します
byte[] result = null;
string reportPath = "/DBGrowth/USRTechDBGrowthChart";
string format;
//byte[] reportDefinition; //レポート定義が必要な場合
// = MywebReportServer.GetReportDefinition(reportName);
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
//Base 64 エンコードのバイト配列としてのレポート定義
ParameterValue[] parameters = new ParameterValue[1];
parameters[0] = new ParameterValue();
parameters[0].Name = "propertyname";
parameters[0].Value = "変数";
DataSourceCredentials[] credentials = null;
Warning[] warnings = null;
ParameterValue[] reportHistoryParameters = null;
string[] streamIDs = null;
SessionHeader sh = new SessionHeader();
MywebReportServer.SessionHeaderValue = sh;
try{ // バイナリを XML ドキュメントに読み込みます
format = "XML";
result = MywebReportServer.Render(reportPath, format, historyID, devInfo, parameters, credentials,
showHideToggle, out encoding, out mimeType, out reportHistoryParameters, out warnings, out streamIDs);
doc.Load(new System.IO.MemoryStream(result));
doc.Save(Savepath + "report.xml");
Console.WriteLine( "結果が XML ファイルに保存されました" );
//必要な場合は、他の形式を指定できます
//たとえば、format = "CSV" または format = "MHTML";
return true;
catch (Exception e){
Console.WriteLine("{0} 例外がキャッチされました。", e);
Console.WriteLine("{0} 例外がキャッチされました。", e.Message); }
return false; }
返された結果をさらに処理する場合は、XSL 変換を適用するか、またはデータをデータセットとして取得し、他のソースからのデータをマージすることができます。
上記の例では、メモリ ストリームを XML ドキュメントに読み込みます (SOAP 呼び出しはエンコードされた byte[] 配列を返しました)。代わりに、メモリ ストリームをデータセットに読み込み、さらに XSLT を適用できます。
byte[] result = MywebReportServer.Render(...); MemoryStream stream = new MemoryStream(renderResult); DataSet MyDs = new DataSet(); MyDs.ReadXml(stream); System.IO.StringReader(MyDs.GetXml())); System.Xml.Xsl.XslTransform xslt = new System.Xml.Xsl.XslTransform(); xslt.Load(@"c:\xmltest\mySchema.xslt");
XML データを SQL 2000 Server にアップロードする
XML Bulk Load は、XML データを SQL Server のテーブルに読み込めるスタンドアロン COM オブジェクトです。内部的には、ネイティブの SQLOLEDB プロバイダに付属の bcp に似たメカニズムを使用します。XML Bulk Load は COM オブジェクトなので、ADO、Visual Basic スクリプト、または .NET アプリケーションでも使用できます。
次のサンプル コードでは、"SQLXMLBULKLOAD" を使用して XML ドキュメントを SQL Server に直接読み込む方法を示しています (Visual Studio C# プロジェクトの COM での参照に "Microsoft XML BulkLoad for SQL Server 3.0 Type Library" を追加します)。また、COM オブジェクトなので 1 つの問題が生じます。この関数の呼び出し中はスレッド モデルを STA にする必要があります。
詳細については、「Using SQLXML Bulkload in the .NET Framework」を参照してください。
public bool BulkLoad(string SourceSavePath, string ConnectionStr,
string MyXsdFile, string MyXMLFile ) {
bool test;
try{
Type Mytype;
SQLXMLBulkLoad objBL = new SQLXMLBulkLoad();
objBL.ConnectionString=ConnectionStr;
objBL.ErrorLogFile = SourceSavePath + "\\" + "error.log";
objBL.CheckConstraints = true;
test = objBL.Transaction;
objBL.TempFilePath=SourceSavePath;
objBL.XMLFragment = true;
objBL.SchemaGen = true;
objBL.SGDropTables = true;
objBL.Execute(SourceSavePath + "\\" + MyXsdFile, SourceSavePath + "\\" + MyXMLFile);
return true; }
catch (Exception e) {
Console.WriteLine("{0} 例外がキャッチされました。", e); }
return false;}
まず、コードを実行する前に、データのアップロード先のテーブルを、適切なキーを付けて SQL Server 上に作成する必要があります。つまり、SQL Server には、テーブルが前もって存在している必要があります。コードを実行します。
objBL.SchemaGen = true; objBL.SGDropTables = true;
上記のコードにより、実際にテーブルが削除された後再作成され、データが XML ファイルから読み込まれます。読み込みプロセスが完了すると、ジョブ ステップとして TSQL を使用してインデックスや制約を追加できます。テーブル スキーマは、指定する XSD ファイル (このコード例では MyXsdFile) から作成されます。SQLXMLBULKLOAD では、要素、および XSD スキーマのからの属性名と型情報を使用して、テーブルが生成されます。これは、この記事で既に説明したマッピング スキーマおよび注釈付きスキーマ (つまり、XML ビューの作成に使用される XDR ファイル) に似ています。
XSD スキーマ ファイルは、XML データのコンテンツや構造を記述する場合によく使用されます。SQLXML 固有のマッピング注釈は、xmlns:sql="urn:schemas-microsoft-com: mapping-schema 名前空間に属しています。
たとえば、"ROOT" というルート要素名を使用する XML ファイルがあり、FirstName と LastName という 2 つの属性を持つ Customer という要素名を使用するファイルがあるとします。このタスクでは、XML ファイルの顧客データを、2 つの列 (SQLColumnFirstName と SQLColumnLastName) を含む SQLCustomerTable という名前の SQL テーブルに読み込みます。実際には、さらに多くの属性や列がこのテーブルに含まれることになります。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sql="urn:schemas-microsoft-com:mapping-schema">
<xsd:element name=" ROOT " sql:is-constant="true" >
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Customer" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="Customer" sql:relation="SQLCustomerTable" >
<xsd:complexType>
<xsd:attribute name="FirstName" sql:field="SQLColumnFirstName" sql:datatype="varchar(100)" />
<xsd:attribute name="LastName" sql:field="SQLColumnLastName" sql:datatype="varchar(100)" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
注: 他の代替手段として SQL Server 2000 の "OPENXML" を使用する場合には、MSXML でのスケーラビリティとメモリの問題、XML ファイルまたは UNC ファイル パスを直接渡せない、XML はインラインにする必要がある、文字列として渡す、XML を Ntext パラメータとして受け取るストアド プロシージャ内部で使用する必要があるなど、厳しい制限があります。
まとめ
この記事では、SQL データを XML コードとして保存するためのいくつかの技法について説明しています。データは、Web サービス、XML Web サービス、および SQL Reporting Services を使用して、SQL Server から直接公開されます。
従来の方法には、COM を使用する ASP や ASPX、および ADO モデルを使用する "URL アクセス" などがあります。.NET Framework では、SQL Server からの XML ストリームを処理するために、ADO.NET データセット、および XmlTextReader クラスと XmlTextWriter クラスも使用できます。ストアド プロシージャで "FOR XML" 句と XmlTextReader や XmlTextWriter ストリーミング API クラスを使用する方法もあります。どちらの場合も、ビジネス アプリケーションの必要に応じて、XSLT、XDR スキーマ、XPath を使用して XML データをさらに処理して書式を設定できます。.NET 特有の機能として、XML を XML Web サービス メソッド経由で公開し、SOAP プロトコルを使用してさまざまなプラットフォームからアクセスできます。
また、SQL Reporting Services からのデータも XML Web サービスとして公開され、SOAP メッセージングを使用してどこからでもアクセスできます。つまり、レポートのデータは、XML ファイルとしてダウンロードできます。一連の処理サイクルを完了するために、データを SQL Server に再度アップロードする場合は、SQLXMLBULKLOAD オブジェクト モデルを使用することが最も効果的な方法です。
参考資料
XPath Querying Over Objects with ObjectXPathNavigator
The Best of Both Worlds: Combining XPath with the XmlReader
DataSetNavigator を使用した DataSet に対する XPath クエリ
Manipulate XML Data Easily with the XPath and XSLT APIs in the .NET Framework
Chapter 9-Improving XML Performance
著者について
"Venkat Prasad (MCDBA、MCSD)" は、MSN のデータベース開発者兼エンジニアです。監視ツール、および SQL Server や SQL Reporting Services で実行する ETL プロジェクトとデータウェア ハウジング プロジェクトを担当しています。