50 votes

.Net - Retour de DataTables dans WCF

J'ai un service WCF à partir de laquelle je souhaite retourner un DataTable. Je sais que c'est souvent un sujet très controversé, quant à savoir si ou de ne pas retourner les tables de données est une bonne pratique. Mettons cela de côté pour un moment.

Quand j'ai créer une Table de données à partir de zéro, comme ci-dessous, il n'y a aucun problème que ce soit. La table est créée, renseigné et retourné au client, et tout est bien:

[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;
}

Cependant, dès que je sors, et de frapper la base de données pour créer le tableau, ci-dessous, je reçois un CommunicationException "La connexion sous-jacente a été fermée: La connexion a été fermée de façon inattendue."

[DataContract]
public DataTable GetTbl()
{
    DataTable tbl = new DataTable("testTbl");
    //populate table with sql query
    return tbl;
}

La table est remplie correctement sur le côté serveur. Il est beaucoup plus petite que la table de test que j'ai bouclé et retourné, et la requête est petit et rapide, il n'est pas question ici avec des délais d'attente ou de transfert de données volumineuses. Exactement les mêmes fonctions et DataContracts/ServiceContracts/BehaviorContracts sont utilisés.

Pourquoi la façon dont la table est remplie a aucune incidence sur la table son retour avec succès??

82voto

goric Points 5230

Pour toute personne ayant des problèmes similaires, j'ai résolu mon problème. Il était plusieurs fois.

  • Comme Darren suggéré et Paul sauvegardé, le Max..propriétés de Taille dans la configuration devrait être élargi. Le SvcTraceViewer utilitaire aidé dans la détermination de cette, mais elle ne donne pas toujours les plus utiles messages d'erreur.
  • Il apparaît également que lorsque le Service de Référence est mis à jour sur le côté client, la configuration sera parfois pas à jour correctement (par exemple, Changement de config valeurs sur le serveur ne sera pas toujours correctement mise à jour sur le client. J'ai dû aller et de modifier les Max..propriétés de Taille à plusieurs reprises sur les deux côtés client et serveur dans le cadre de mon débogage)
  • Mon dernier problème semble être que la DataTable n'a pas été initialisé avec un nom. Je suis encore à essayer de comprendre pourquoi cela est important, mais ce:

    return new DataTable();
    

    échoue, où ce:

    return new DataTable("someName");
    

    ne sera pas. Toute entrée sur ce serait génial.

J'espère que ça va aider quelqu'un.

15voto

Chris Gillum Points 3782

La meilleure façon de diagnostiquer ce genre de WCF erreurs (celles qui n'ont pas vraiment vous en dire beaucoup) est de permettre le suivi. Dans votre site web.fichier de config, ajoutez la ligne suivante:

  <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>

Vous pouvez ensuite ouvrir le fichier obtenu dans le SvcTraceViewer.exe utilitaire qui vient dans la .NET Framework SDK (ou avec Visual Studio). Sur ma machine, il peut être trouvé dans le dossier %PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\Bin\SvcTraceViewer.exe.

Il suffit de regarder pour un message d'erreur (en rouge et en gras) et qui va vous dire précisément quel est ton problème.

5voto

Jani5e Points 73

J'ai ajouté le Datable à un ensemble de données et renvoyé la table comme si ...

 DataTable result = new DataTable("result");

//linq to populate the table

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

J'espère que ça aide :)

5voto

aditya pathak Points 21

Autre que ses valeurs maximales pour tous les attributs de liaison.

Assurez-vous que chaque table que vous passez / retournez du service Web doit avoir le nom de table, ce qui signifie que la propriété nom_table ne doit pas être vide.

3voto

Darren Kopp Points 27704

L'attribut que vous voulez, c'est OperationContract (de l'interface) / Opération de Comportement (de la méthode)

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


[OperationBehavior]
public DataTable GetTbl(){    
    DataTable tbl = new DataTable("testTbl");    
    //populate table with sql query    
    return tbl;
}

Aussi, dans le... je pense que la configuration du service... vous souhaitez indiquer que les erreurs qui peuvent être envoyés, vous risquez de vous frapper une erreur qui est quelque chose comme la taille du message est au grand, etc. Vous pouvez corriger cela en fausser w/ le lecteur de quotas et de ces. Par défaut wsHttpBinding a un de recevoir de la taille de quota comme 65k, donc si les données sérialisées table xml est plus que cela, il serait jeter une erreur (et je suis sûr à 95% que la table de données est plus de 65k avec les données qu'il contient)

Vous pouvez modifier les paramètres du lecteur de quotas et de tel dans le web.config / app.config ou vous pouvez le mettre sur une liaison de l'instance dans le code. Mais ouais, c'est probablement ce que votre problème est, si vous ne l'avez pas changé par défaut.

WSHttpBindingBase Membres - Regarder ReaderQuotas bien, ainsi que le MaxReceivedMessageSize propriété

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X