Archiv für die Kategorie "Windows"

Einem WCF Dienst aus PHP ein Dictionary als Parameter übergeben

Einem WCF Dienst ein Dictionary (hier Dictionary<string, string>) als Parameter zu übergeben, kann z.B. sinnvoll sein, wenn der Dienst eine Suche in einer SQL-Datenbank durchführen soll, wobei die SQL-Abfrage, die dieser Suche zu Grunde liegt, beliebig viele SQL-Parameter enthalten kann:

SELECT
    *
FROM
    [TABLE]
WHERE
    FIELD1 LIKE @Search1
    FIELD2 LIKE @Search2
    FIELD3 LIKE @Search3
    ...
    FIELDN LIKE @SearchN

Die entsprechende Methode des Dienstes könnte dann so aussehen (die Deklaration als void um so einfach wie möglich zu bleiben):

public void SendDictString(Dictionary<string, string> dParam)
{
    SqlCommand sc = new SqlCommand();
    sc.CommandText = ...; // Die SQL-Abfrage, z.B. aus Datei geladen

    Dictionary<string,string>.Enumerator e = dParam.GetEnumerator();
    while (e.MoveNext())
    {
        Debug("{0}:{1}", e.Current.Key.ToString(), e.Current.Value.ToString());

        sc.Parameters.Add(new SqlParameter(e.Current.Key, e.Current.Value));
    }
    SqlDataReader sdr = sc.ExecuteReader();
}

Betrachtet man die resultierende WSDL-Datei, sieht diese so aus:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<xs:complexType name="ArrayOfKeyValueOfstringstring">
<xs:annotation>
<xs:appinfo>
<IsDictionary xmlns="http://schemas.microsoft.com/2003/10/Serialization/">true</IsDictionary>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="KeyValueOfstringstring">
<xs:complexType>
<xs:sequence>
<xs:element name="Key" nillable="true" type="xs:string"/>
<xs:element name="Value" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfKeyValueOfstringstring" nillable="true" type="tns:ArrayOfKeyValueOfstringstring"/>
</xs:schema>

Interessant an dieser Beschreibung ist dieser Teil:

<xs:sequence>
<xs:element name="Key" nillable="true" type="xs:string"/>
<xs:element name="Value" nillable="true" type="xs:string"/>
</xs:sequence>

Mit einer PHP-Anwendung ließe sich der Dienst entsprechend wie folgt konsumieren:

$client->SendDictString(array(
	"dParam"	=>	array(
		array(
			"Key"	=>	"Search1",
			"Value"	=>	"Suchbegriff1"
		),
		array(
			"Key"	=>	"Search2",
			"Value"	=>	"Suchbegriff2"
		),
		array(
			"Key"	=>	"Search3",
			"Value"	=>	"Suchbegriff3"
		)
	)
)

Die Debug-Ausgabe des WCF Dienst sieht dann so aus:

Search1:Suchbegriff1
Search2:Suchbegriff2
Search3:Suchbegriff3
Share
Geschrieben von Philip Ehret am 15.07.2011 | Kommentare weiterlesen...

Fehlermeldung „Error Fetching http headers“ bei der Abfrage eines WCF Dienstes, welcher einen benutzerdefinierten Typ zurückgibt

Bei der Entwicklung eines WCF WebService, definierte ich den folgenden ServiceContract:

[ServiceContract]
public interface IClient
{
    ...
    [OperationContract]
    WebUser GetUserData(string sWebUserHash);
    ...
}

Beim Abruf einer Implementierung des Dienstes mit Hilfe des PHP SoapClient kam es zu der Exception:

Error Fetching http headers

Zwar hat mich die Suche nach dem Ursprung unter anderem zu einem PHP Bug Report geführt, jedoch konnten die dort angegebenen Hilfen mein Problem nicht beheben.

Da die Kompilierung des WebService ohne Probleme verlief, die Dienstbeschreibung per HTTP abrufbar war und andere Methoden ohne Probleme funktionierten, vermutete ich das Problem beim PHP SoapClient. Jedoch stellte sich dann heraus, dass ich vergessen hatte, dem WebService den Typ WebUser bekanntzumachen.

Das Problem löste sich durch die simple Ergänzung des folgenden Attributs:

[ServiceKnownType(typeof(WebUser))]

Der funktionierende Quellcode sah dann so aus:

[ServiceContract]
[ServiceKnownType(typeof(WebUser))]
public interface IClient
{
    ...
    [OperationContract]
    WebUser GetUserData(string sWebUserHash);
    ...
}
Share
Geschrieben von Philip Ehret am 30.06.2011 | Kommentare weiterlesen...

Microsoft SQL Server: Problem mit dem GO-Schlüsselwort beim Verwenden des JDBC-Treibers

Arbeitet man mit dem Microsoft SQL Server, so wird man viel und oft das Schlüsselwort GO verwenden. Sollen Serverabfragen, die das GO-Schlüsselwort enthalten, mit JDBC ausgeführt werden, kommt es jedoch zu einer Ausnahme (Exception):

Falsche Syntax in der Nähe von ‚GO‘.

Anstatt alle SQL-Skripte, die das GO-Schlüsselwort enthalten, umzuschreiben, gibt es auch eine einfachere Möglichkeit in Java: Man zerlegt ein SQL-Skript einfach anhand des GO-Schlüsselworts und packt jedes Teilelement in ein eigenes JDBC-Statement.

Wir gehen von folgendem SQL-Skript aus:

USE [someDatabase]
GO

CREATE VIEW [someSchema].[someView] AS SELECT * FROM [someSchema].[someTable]
GO

CREATE TABLE [someSchema].[someTable] (
	someField VARCHAR(50) NULL
)
GO

Dann lassen sich alle Teile wie folgt ausführen:

Connection con; // Eine aktive Verbindung zu einem SQL-Server via JDBC 
String sql; // Oben genanntes SQL-Skript

for(String batch: sql.split("GO")){
	con.createStatement(batch.trim()).execute();
}
Share
Geschrieben von Philip Ehret am 09.02.2011 | Kommentare weiterlesen...