Delphi調用.NET的WebService

問題的來源請參考gattaca的留言,雖然問題狠簡單,但是對於不熟悉ClientaDataSet的人來說,還是值得研究的。本例將實現一個基於.NET的WebService,並且使用Delphi調用,獲取數據。

首先開發一個WebService,我使用VS2008下C#語言進行開發,新建一個ASP.NET Web Service工程,代碼如下:
[WebMethod]
    public string GetData() {
        string ConnStr = "Provider=SQLOLEDB.1;Password=\"\";Persist Security Info=True;User ID=sa;Initial Catalog=Northwind;Data Source=192.168.1.100";
        OleDbConnection myConnection = new OleDbConnection(ConnStr);
        string strSQL = "select * from Employees";
        OleDbDataAdapter myAdapter = new OleDbDataAdapter(strSQL, myConnection);
        DataSet ds = new DataSet();
        myAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
        myAdapter.Fill(ds, "Employees");

        return CSDS2DDS.ToClientDataSet(ds, "Employees");
    }

其中CSDS2DDS是CSharpDataSetToDelphiDataSet的縮寫,它包含一個靜態方法,用於將.NET的數據集轉換為ClientDataSet所使用的XML。這個類的代碼如下:
public class CSDS2DDS {
public CSDS2DDS() {
}

    public static string ToClientDataSet(DataSet ds, string TableName) {
        int FieldCount = ds.Tables[TableName].Columns.Count;
        string result = "<?xml version=\"1.0\" standalone=\"yes\"?>";
        result += "<DATAPACKET Version=\"2.0\">";
        result += "<METADATA><FIELDS>";
        for (int i = 0; i < FieldCount; i++) {
            DataColumn dc = ds.Tables[TableName].Columns[i];
            string FieldType = dc.DataType.Name.ToLower();
            // integer
            if (FieldType.ToLower() == "int32")
                FieldType = "i4";
            // int64
            if (FieldType.ToLower() == "int64")
                FieldType = "i8";
            // float
            if (FieldType.ToLower() == "single")
                FieldType = "r8";
            // memo
            if (FieldType.ToLower() == "string" && dc.MaxLength > 255)
                FieldType = "bin.hex";
            // bytes
            if (FieldType.ToLower() == "byte[]")
                FieldType = "bin.hex";
            result += string.Format("<FIELD attrname=\"{0}\" fieldtype=\"{1}\" ", dc.ColumnName, FieldType);
            if (FieldType == "bin.hex" && dc.DataType.Name.ToLower() == "string")
                result += "SUBTYPE=\"Text\" ";
            else if (FieldType == "string")
                result += string.Format("WIDTH=\"{0}\" ", dc.MaxLength);
            else if (FieldType == "sqldatetime")
                result += "SUBTYPE=\"Formatted\"";
            else if (FieldType == "bin.hex" && dc.DataType.Name.ToLower() != "string" || dc.DataType.Name.ToLower() == "byte[]")
                result += "SUBTYPE=\"Binary\"";
            result += "/>";
        }
        result += "</FIELDS><PARAMS/></METADATA>";
        result += "<ROWDATA>";
        int RowCount = ds.Tables[TableName].Rows.Count;
        for (int i = 0; i < RowCount; i++) {
            result += "<ROW RowState=\"4\" ";
            for (int j = 0; j < FieldCount; j++) {
                DataTable dt = ds.Tables[TableName];
                string value = dt.Rows[i].ItemArray[j].ToString();
                value = value.Replace("\"", "&quot;");
                result += string.Format("{0}=\"{1}\" ",
                    dt.Columns[j].ColumnName,
                    value);
            }
            result += "/>";
        }
        result += "</ROWDATA></DATAPACKET>";
        return result;
    }
}
這個類非常明確,就是用循環的方式讀出.NET數據集中的數據,並且拼裝成ClientDataSet使用的XML
做完這一步,就可以將WebService部署去IIS,然後用Delphi直接調用了,用WSDL Importer或RO引入WSDL,生成單元後就可以調用它。
procedure TForm1.FormCreate(Sender: TObject);
var
xml: string;
begin
xml := Service.GetServiceSoap.GetData;
ClientDataSet1.XMLData := xml;
ClientDataSet1.Open;
end;
程序執行後即可看到,數據從.NET端傳遞到了Delphi端。
由於轉換的代碼直接讀取.NET的數據集,因此對delphi端沒有任何影響。
如果以後.NET的數據集發生了改變,也只需要在服務器上直接修改轉換代碼,.NET數據集的格式改變的可能性非常小。至少從.NET1.1開始,到現在的.NET3.5,它完全沒有改變過。

注意:部署WebService時請使用IIS6.0,盡量使用Windows2003,如果用XP,可能會產生不可預知的問題。

posted @ 2009-11-19 08:59  大漠银狐  阅读(855)  评论(0编辑  收藏  举报