none
Mehrere gleichzeitige Datenverbindungen mit LinQ RRS feed

  • Frage

  • Guten Tag alle zusammen,

    Wir haben ein etwas komplexeres Programm für unsere Facharbeit geschrieben und hängen nun leider an einem Problem, dass sich uns erst vor kurzem aufgetan hat.

    Zum kurzen Überblick: Wir haben einen WCF Dienst, der mit Hilfe von LinQ auf eine Datenbank zugreift und sich dort Werte holt, bzw. in diese hinein schreibt. Zusätzlich ist derzeit der einzige Consumer dieses Dienstes ein Silverlight Client, der ja bekanntermaßen die generierten Dienstmethoden nur asynchron aufrufen kann. Und da ist auch schon das Problem: Wenn der Client eine Methode auf dem Dienst aufruft und diese Methode etwas aus der Datenbank zieht und zusätzlich (da asynchron) eine weitere Methode aufruft, die ebenfalls etwas an der Datenbank macht, wird ein Fehler geworfen, dass dem DataContext bereits ein geöffneter DataReader zugeordnet ist.

    Das große Problem daran ist, dass man zwar verhindern könnte, dass der Client solche Aufrufe asynchron durchführt, aber dann besteht immer noch das Problem, da ja mehrere Clients gleichzeitig auf den Dienst zugreifen können/sollen und damit das Risiko dieses Fehlers wieder steigt.

    Wir verwenden folgende Produkte/Technologien: MS SQL Server 2008 R2 Express (lokal), Azure SQL (internet), VS 2010, .NET 4.0

    Ich habe bereits ein wenig im Internet geschaut und herausgefunden, dass es eine Technik namens MARS gibt. Leider hat das einfache anpassen des ConnectionStrings keine Besserung gebracht.

    Ich hoffe sehr, hier Jemanden zu finden, der uns bei der Lösung des Problemes behilflich sein kann. Wir können uns nicht vorstellen, dass es keine Lösung dafür gibt, da ja auch Webseiten quasi von diesem Problem betroffen wären und bspw. CMS Systeme überhaupt nicht funktionieren würden.

    Gerne gebe ich mehr Informationen, falls diese benötigt werden.

    Mit freundlichen Grüßen
    Christopher

    Donnerstag, 28. April 2011 13:51

Antworten

Alle Antworten

  • Hallo Christopher,

    ein WCF Dienst sollte so weit wie möglich zustandsfrei geschrieben werden.
    Im Falle von Datenbankverbindungen sollte jeder Zugriff eine eigene Verbindung öffnen
    (und direkt nach der Ausführung schließen).
    Dann sind auch mehrfache (asynchrone) Zugriffe kein Problem.

    MARS wäre nur hilfreich, wenn mehrere DataReader innerhalb eines Aufrufs benötigt werden.

    Leichter ist es im allgemeinen die WCF RIA Services  (MSDN) zu verwenden,
    womit man einen Großteil des Datenbank-Zugriffes frei Haus kriegt.

    Falls ihr jedoch im Rahmen eurer Arbeit dies selbst schreiben müsst,
    so wäre es hilfreich, wenn Du einen Ausschnitt eures Programms zeigst
    bzw. zum Download (z. B. SkyDrive) bereitstellst.

    Gruß Elmar

     

    Donnerstag, 28. April 2011 14:34
    Beantworter
  • Hallo Elmar,

    vielen Dank zunächst für die schnelle Antwort.

    MARS wäre nur hilfreich, wenn mehrere DataReader innerhalb eines Aufrufs benötigt werden.

    Okay, damit hätte sich das schon einmal erledigt. Ich hatte leider nicht die Zeit dazu, mir das genauer anzuschauen. Ich dachte mir, dass die Lösung ja vielleicht so einfach hätte sein können :)

    Leichter ist es im allgemeinen die WCF RIA Services zu verwenden

    Eine weitere Technologie, die ich noch nie verwendet habe. Soweit ich weiß funktionieren diese jedoch nicht im Silverlight for Windows Phones? Um dieses Silverlight soll es sich Schlussendlich handeln (ich erwähnte es nicht, da ich dachte, dass es unerheblich ist, da die Dienstaufrufe ja trotzdem gleich funktionieren)

     

    ein WCF Dienst sollte so weit wie möglich zustandsfrei geschrieben werden. Im Falle von Datenbankverbindungen sollte jeder Zugriff eine eigene Verbindung öffnen (und direkt nach der Ausführung schließen). Dann sind auch mehrfache (asynchrone) Zugriffe kein Problem.

    So wie du es beschreibst, benötige ich also für jede Dienstinstanz (die ja bei jedem Aufruf einer Methode neu generiert wird) eine neue Instanz meines Datenkontextes und damit auch eine neue Verbindung. Daraus schliesse ich, dass es durchaus möglich ist, mehrere Verbindungen (gibt es da ein Limit?) auf den Server zu erhalten, dass es aber widerrum nicht möglich ist, mit dem gleichen Datenkontext asynchron Abfragen an den Server zu schicken. Liege ich da soweit richtig? Wenn ja, wäre es ja das einfachste direkt vor jedem Datanbankabruf ein neues Datenkontext-Objekt zu initialisieren und nach der Abfrage zu schliessen.

    Liebe Grüße, Christopher

    Donnerstag, 28. April 2011 15:14
  • Hallo Christopher,

    mit Windows Phone habe ich wenig am Ohr ;-)
    Über die WCF Data Services geht aber auch dies. Siehe z. B.:
    Exercise 1: Connecting Windows Phone 7 with WCF Data Services
    was auch asynchrone Aufrufe und in Verbindung mit Azure zeigt.
    Und Sacha Barber: Introduction to ADO.NET Data Services/RIA Services

    Zur Unterscheidung RIA vs Data Services et. al.:
    http://blogs.msdn.com/b/endpoint/archive/2010/01/04/wcf-data-services-ria-services-alignment-questions-and-answers.aspx
    erklärt den mittlerweile bei Microsoft zu häufigen Technologie Wirrwarr.

    Zum weiteren: Ein SQL Server kann bis zu 32768 Verbindungen verwalten.
    Ein Service wird diese kaum auf einmal erreichen; wenn ja, wird man vorher andere
    (Last-)Probleme bekommen, so man sich um Last-Verteilung etc. kümmern müsste.

    Das es auch für High-End geht, zeigt Stackoverflow:
    http://meta.stackoverflow.com/questions/43991/implement-odata-api-for-stackoverflow

    Vielmehr ist es so, dass Du die Verbindung idealerweise nur kurzzeitig offen hältst,
    und danach wieder freigibst (Dispose) so dass sie erneut genutzt werden können.

    Beim Entity Framework wird das automatisch gemacht, siehe
    Verwalten von Verbindungen und Transaktionen (Entity Framework)
    (äquivalentes gilt für LINQ To SQL)

    Die oben angesprochenen Data Services selbst wiederum sind zustandslos,
    Dort verwaltet der lokale DataServiceContext den Zustand.

    Gruß Elmar

    Donnerstag, 28. April 2011 16:15
    Beantworter
  • Servus Elmar,

    vielen Dank für das Raussuchen der Links - ich bin derzeit immer noch am Lesen und Ausprobieren (RIA, Entitiy Framework).

    Zu unserer Facharbeit kann ich sagen, dass wir das Problem nun ganz einfach beheben konnten. Entsprechende Datenverbindungen werden nun Sessionabhängig verteilt und werden immer neu geöffnet, wenn eine entsprechende Änderung vorliegt. Das war auch ein sehr guter Zeitpunkt mehr über Change Conflicts in LinQ zu erfahren.

    Tja und nun ist sie fertig - es war auf jedenfall sehr lehrreich. Schade nur, dass das große Projekt jetzt wahrscheinlich einfach verstauben wird.

    Danke nochmals für die schnelle Hilfe

    Mit freundlichen grüßen
    Christopher Kellner

     

    Samstag, 30. April 2011 12:33
  • Hallo Christopher,

    wenn ihr aus dem Facharbeit was lernt, hat es sich alle Male gelohnt!

    Das Schicksal der Arbeit als solches (mit einer hoffentlich guten Note) ist dann nicht so wichtig.

    Gruß Elmar

    Samstag, 30. April 2011 14:53
    Beantworter