locked
WCF Contract "Design Guidelines" RRS feed

  • Frage

  • Hallo zusammen,

    ich beschäftige mich derzeit mit WCF Contracts und bin da auf eine interessante Frage zum Thema Design von WCF Contracts gestossen, und würde gerne mal Eure Meinungen und Anregungen hierzu hören:

    Wie werden Auflistung von Objekten am besten(sinnvollsten/schönsten...) übertragen?

    (Vereinfachtes) Beispiel hierzu von meiner Seite: Es sollen (Kind-)Objekte aus einer hierachischen Struktur übertragen werden (vergleichbar mit Dateien/Ordnern aus einem Dateisystem). Als Beispielmethode dient das Abrufen von Kindelementen eines übergeordneten Elements:

    GetChildItemsResponse[] GetChildItems(GetChildItemsRequest request);

    Was hier schon mal beachtet wurde, ist die Tatsache dass (ein evtl. einzusetzendes) MSMQ nur jeweils mit einem Parameter umgehen kann, daher die Kapselung in die Request- bzw. Responseklassen. Allerdings habe ich in diversen Blogs gelesen, dass man wohl besser keine Auflistungen/Arrays direkt übergeben sollte, sondern nur als Property.

    GetChildItemsResponse GetChildItems(GetChildItemsRequest request);

    Mit irgendetwas derartigem:

    public class GetChildItemsResponse
            {
                public Item[] Items { get; set; }
            }

    Das scheint mit auf den ersten Blick eigentlich ein völlig legitimer Ansatz zu sein - allerdings gibt's ein gewichtiges Argument dagegen: Die potentiell mögliche Antwortgröße. Da WCF per default erstmal sehr "konservative" Werte für mögliche Messagegrößen definiert, läuft das hier schnell aus dem Ruder (sprich: auf Exception).

    Daher der nächste Ansatz:

    GetNextChildItemResponse GetNextChildItem(GetNextChildItemRequest request);

    Wobei hier jeweils nur ein einzelnes Element zurückgeliefert wird, und im Request ein (irgendwie gearteter) Zeiger auf das vorherige Element enthalten sein muss.

    Freude Für diejenigen die's noch "von früher" kennen: Sehr verleichbar mit FindFirstFile bzw. FindNextFile aus der Windows-API.

    Den Ansatz finde ich persönlich eigentlich sehr schön (und bevorzuge ihn deshalb auch) - zumal er sich noch wunderbar auf Clientseite an IEnuerable<T> Typen "binden" lässt.


    Nun bin ich allerdings an einer Stelle angekommen, wo dieses Vorgehen "problematisch" werden könnte:
    Was ist, wenn das Zusammenstellen der Ergebnisse für den Client sehr aufwendig ist?
    Wenn der Server hier z.B. eine komplexe Operation durchführen muss um die Kindelemente zu ermitteln, dann aber nur eines davon an den Client übergibt...
    Ich sehe hier zwei Mögliche Vorgehensweisen:

       1. Der Server führ die Operationen n mal durch und liefert jeweils ein Ergebnis (das halte ich allerdings für "suboptimal")
       2. Der Server muss in irgendeiner Form die Ergebnisse cachen und mit einem (irgendwie geartetem) Zeiger über die Ergebnisse iterieren.

    Der (aus meiner Sicht) "saubere" Weg ist wohl der letztgenannte - allerdings muss dann erstmal die ganze Infrastruktur für das Caching geschaffen werden. Und da frage ich mich, ob es nicht sinnvoller wäre, zu der Variante von oben (mit dem Array als Property der Response) zu wechseln...

    Bart Simpson

    Freitag, 19. März 2010 14:27

Alle Antworten

  • Guten Abend.

    Ich sehe in meiner doch eher noch geringen Erfahrung im WCF Bereich noch eine mögliche Alternative:

    Und zwar wäre es doch sicherlich möglich sich vor dem Anfordern der jeweiligen ChildItems eines Requests zunächst die Anzahl der ChildItems zu besorgen, die bei einem solchen Request zurückgegeben werden. Anhand der zurückgegebenen Anzahl kann der Client schonmal entscheiden, wieviele Items er zunächst zurückgegeben haben möchte, was dann innerhalb der Methode, die die ChildItems wirklich anfordert, mitgeliefert werden könnte.

    Ich gehe mal davon aus, dass gegeben der Tatsache "Der Server führ die Operationen n mal durch und liefert jeweils ein Ergebnis" eine Art DuplexBinding dafür genutzt wird, da ich mir darunter nur ein Request für mehrere Responses vorstelle. Damit würden schon einmal anstelle von einem Element n Elemente zurückgegeben, wobei n < der Gesamtzahl aller ChildItems ist (sein könnte). Nachteil des Ganzen ist hierbei natürlich die zusätzliche Arbeit auf Serverseite die Anzahl der ChildItems zu ermitteln.

    Sollte diese Operation auf Serverseite zu anstrengend sein, müsste man das ganze irgendwie Cachen, wie schon gesagt wurde. Ich könnte mir darunter eine etwas einfache Variante vorstellen, bei der bei jedem Request einfach ein Hash als Identifizierer mitgegeben wird und auf Serverseite ein Objekt des Typs Dictionary<String><Stack<ChildItem>> als Cache genutzt werden könnte, was den Vorteil besäße, dass man bei jedem weiteren Anfordern von weiteren ChildItems des Results einfach nur die Anzahl der angeforderten Items aus dem Stack nehmen und zurückgeben müsste.

    Vielleicht bringt diese Idee ja etwas und falls in meinem Post irgendwelche Denkfehler zu finden sind, dann bitte immer her damit.
    Aber Möglicherweise wurde bereits eine bessere Alternative gefunden. Wenn ja, würde ich mich auch sehr für diese Alternative interessieren.

    Mit freundlichen Grüßen,
    Christopher Kellner 

    Montag, 29. März 2010 21:00
  • Ich muss zugeben, ich hab bisher nicht an ein Duplex Binding gedacht. Den Ansatz finde ich eingentlich sehr schön - aber er zwingt mich dann natürlich auch ein Duplex Binding zu verwenden (und ich weiss noch nicht, ob ich das will/kann)...

    Der Ansatz, erst mal nach der Anzahl der Items zu fragen klingt zwar eingentlich auch gut, bringt mir aber hier konkret nichts... Die tatsächliche Anzahl kenne ich (in meinem Anwendungsfall) leider erst nachdem der Server alles zusammengestellt hat.

    Aus Deiner Antwort zum Caching lese ich die gleichen Bendenken heraus - es ist erst mal ein ziemlich hoher Aufwand nötig um eine gewisse "Grundinfrastruktur" zu schaffen. Und man muss dabei natürlich immer mit den üblichen Problemen die so einem Mechanismus anhaften "leben"...

    Bart Simpson

    Dienstag, 30. März 2010 07:50