Frage

Ich habe einen WCF-Dienst, von dem ich eine DataTable zurückgeben möchte.Ich weiß, dass dies oft ein heftig diskutiertes Thema ist, was die Frage angeht, ob die Rückgabe von DataTables eine gute Praxis ist oder nicht.Lassen wir das für einen Moment beiseite.

Wenn ich wie unten beschrieben eine Datentabelle von Grund auf erstelle, gibt es keinerlei Probleme.Die Tabelle wird erstellt, gefüllt und an den Client zurückgegeben, und alles ist in Ordnung:

[DataContract]
public DataTable GetTbl()
{
    DataTable tbl = new DataTable("testTbl");
    for(int i=0;i<100;i++)
    {
        tbl.Columns.Add(i);
        tbl.Rows.Add(new string[]{"testValue"});
    }
    return tbl;
}

Sobald ich jedoch rausgehe und auf die Datenbank zugreife, um die Tabelle wie unten zu erstellen, erhalte ich eine CommunicationException „Die zugrunde liegende Verbindung wurde geschlossen:Die Verbindung wurde unerwartet geschlossen.

[DataContract]
public DataTable GetTbl()
{
    DataTable tbl = new DataTable("testTbl");
    //Populate table with SQL query

    return tbl;
}

Die Tabelle wird serverseitig korrekt gefüllt.Sie ist deutlich kleiner als die Testtabelle, die ich durchlaufen und zurückgegeben habe, und die Abfrage ist klein und schnell – hier gibt es kein Problem mit Zeitüberschreitungen oder großen Datenübertragungen.Es werden genau dieselben Funktionen und DataContracts/ServiceContracts/BehaviorContracts verwendet.

Warum sollte die Art und Weise, wie die Tabelle gefüllt wird, einen Einfluss darauf haben, dass die Tabelle erfolgreich zurückgegeben wird?

War es hilfreich?

Lösung

Für alle, die ähnliche Probleme haben: Ich habe mein Problem gelöst.Es war mehrfach.

  • Wie Darren vorschlug und Paul unterstützte, mussten die Max..Size-Eigenschaften in der Konfiguration vergrößert werden.Das Dienstprogramm SvcTraceViewer hat dabei geholfen, dies zu ermitteln, es gibt jedoch immer noch nicht immer die hilfreichsten Fehlermeldungen aus.
  • Es scheint auch, dass bei der Aktualisierung der Dienstreferenz auf der Clientseite die Konfiguration manchmal nicht ordnungsgemäß aktualisiert wird (z. B.Das Ändern von Konfigurationswerten auf dem Server führt nicht immer zu einer ordnungsgemäßen Aktualisierung auf dem Client.Ich musste im Verlauf meines Debuggings sowohl auf der Client- als auch auf der Serverseite mehrmals die Max.Size-Eigenschaften ändern.)
  • Damit eine DataTable serialisierbar ist, muss ihr ein Name gegeben werden.Der Standardkonstruktor gibt der Tabelle keinen Namen, also:

    return new DataTable();
    

    wird nicht serialisierbar sein, während:

    return new DataTable("someName");
    

    benennt die Tabelle nach dem, was als Parameter übergeben wird.

    Beachten Sie, dass einer Tabelle jederzeit ein Name gegeben werden kann, indem Sie dem eine Zeichenfolge zuweisen TableName Eigenschaft der DataTable.

    var table = new DataTable();
    table.TableName = "someName";
    

Hoffentlich hilft das jemandem.

Andere Tipps

Der beste Weg, diese Art von WCF-Fehlern (die Ihnen wirklich nicht viel sagen) zu diagnostizieren, besteht darin, die Ablaufverfolgung zu aktivieren.Fügen Sie in Ihrer web.config-Datei Folgendes hinzu:

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" 
              switchValue="Information" 
              propagateActivity="true">
        <listeners>
          <add name="ServiceModelTraceListener" 
               type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
               initializeData="wcf-traces.svclog"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

Anschließend können Sie die resultierende Datei im Dienstprogramm SvcTraceViewer.exe öffnen, das im .NET Framework SDK (oder mit Visual Studio) enthalten ist.Auf meinem Computer ist es unter %PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\Bin\SvcTraceViewer.exe zu finden.

Suchen Sie einfach nach einer Fehlermeldung (in fettem Rot), die Ihnen genau sagt, wo Ihr Problem liegt.

Ich habe die Datable zu einem Datensatz hinzugefügt und die Tabelle wie folgt zurückgegeben ...

DataTable result = new DataTable("result");

//linq to populate the table

Dataset ds = new DataSet();
ds.Tables.Add(result);
return ds.Tables[0];

Ich hoffe es hilft :)

Anders als das Festlegen von Maximalwerten für alle Bindungsattribute.

Stellen Sie sicher, dass jede Tabelle, die Sie vom Webservice übergeben/zurückgeben, einen Tabellennamen haben muss table.tablename Die Eigenschaft sollte nicht leer sein.

Das gewünschte Attribut ist OperationContract (auf der Schnittstelle) / Operation Behavior (auf der Methode):

[ServiceContract]
public interface ITableProvider
{
    [OperationContract]
    DataTable GetTbl();
}


[OperationBehavior]
public DataTable GetTbl(){
    DataTable tbl = new DataTable("testTbl");
    //Populate table with SQL query

    return tbl;
}

Auch in der...Ich denke, Dienstkonfiguration ...Sie möchten festlegen, dass Fehler gesendet werden können.Möglicherweise stoßen Sie auf einen Fehler, der etwa darin besteht, dass die Nachrichtengröße zu groß ist usw.Sie können das beheben, indem Sie an den Leserquoten usw. herumfummeln.

Standardmäßig hat wsHttpBinding ein Empfangsgrößenkontingent von etwa 65 KB. Wenn also der XML-Code der serialisierten Datentabelle größer ist, wird ein Fehler ausgegeben (und ich bin zu 95 % sicher, dass die Datentabelle mit den darin enthaltenen Daten mehr als 65 KB groß ist). ).

Die Einstellungen für die Leserkontingente usw. können Sie im ändern web.config / app.config Oder Sie können es für eine Bindungsinstanz im Code festlegen.Aber ja, das ist wahrscheinlich Ihr Problem, wenn Sie es nicht standardmäßig geändert haben.

WSHttpBindingBase-Mitglieder – Sehen Sie sich die Eigenschaft „ReaderQuotas“ sowie die Eigenschaft „MaxReceivedMessageSize“ an.

Wahrscheinlich haben Sie Ihr Kontingent überschritten – die Datentabelle ist größer als die zulässige maximale Paketgröße für Ihre Verbindung.

Sie müssen wahrscheinlich einstellen MaxReceivedMessageSize Und MaxBufferSize zu höheren Werten auf Ihrer Verbindung.

Es gibt drei Gründe für einen fehlgeschlagenen Rückgabetyp: datatable in WCF-Diensten

  • Sie müssen einen Datentabellennamen wie folgt angeben:

    MyTable=new DataTable("tableName");
    
  • Wenn Sie eine Referenz auf der Clientseite des WCF-Dienstes hinzufügen, wählen Sie eine wiederverwendbare DLL aus system.data

  • Geben Sie das Attribut an datatable Mitgliedsvariable wie

    [DataMember]
    public DataTable MyTable{ get; set; }
    

Ich denke, Darren hat höchstwahrscheinlich Recht – die für WCF bereitgestellten Standardwerte sind lächerlich klein, und wenn man darauf stößt, treten Fehler auf, die schwer aufzuspüren sind.Sie scheinen aufzutreten, sobald Sie versuchen, etwas anderes als einen einfachen Testfall zu tun.Ich habe mehr Zeit verschwendet, als mir lieb ist, mit der Fehlersuche bei Problemen, die, wie sich herausstellte, mit den verschiedenen Konfigurations-(Größen-)Einstellungen sowohl auf dem Client als auch auf dem Server zusammenhingen.Ich glaube, ich habe am Ende fast alle geändert, z.MaxBufferPoolSize, MaxBufferSize, MaxConnections, MaxReceivedMessageSize usw.

Allerdings ist das ebenfalls erwähnte Dienstprogramm SvcTraceViewer großartig.Ich bin zwar auf einige Fälle gestoßen, in denen es nicht so hilfreich war, wie ich es mir gewünscht hätte, aber insgesamt ist es ein gutes Tool zur Analyse des Kommunikationsflusses und von Fehlern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top