2010-06-16 2 views
3

J'ai hérité d'une application C# .NET qui parle à un service Web et le service Web parle à une base de données Oracle. J'ai besoin d'ajouter une fonction d'exportation à l'interface utilisateur pour produire une feuille de calcul Excel de certaines données.Quel est le meilleur moyen de transférer un grand ensemble de données sur un service Web ASMX?

J'ai créé une fonction de service Web pour exécuter une requête de base de données, charger les données dans un DataTable, puis les renvoyer, ce qui fonctionne correctement pour un petit nombre de lignes. Cependant, il y a suffisamment de données dans l'exécution complète pour que l'application cliente se verrouille pendant quelques minutes, puis renvoie une erreur de délai d'attente. Évidemment, ce n'est pas la meilleure façon de récupérer un tel ensemble de données. Avant d'aller de l'avant et de trouver une façon douteuse de diviser l'appel, je me demande s'il y a déjà quelque chose en place qui peut gérer cela. En ce moment, je pense à une fonction startExport appelant ensuite une fonction next50Rows jusqu'à ce qu'il n'y ait plus de données, mais comme les services web sont sans état, cela signifie que je vais devoir garder une sorte de numéro d'identification et gérer le autorisations associées. Cela voudrait dire que je n'ai pas besoin de charger l'intégralité de l'ensemble de données dans la mémoire du serveur web, ce qui est une bonne chose.

Donc, si quelqu'un connaît un meilleur moyen de récupérer une grande quantité de données (dans un format de table) sur un service Web ASNM, s'il vous plaît faites le moi savoir!

+0

Combien de données? Êtes-vous sûr que c'est la quantité de données, pas possible la requête ou quelque chose d'autre qui cause cela? – cdonner

+0

Il pourrait s'agir de la requête, c'est seulement quelques milliers de lignes de données. Il ne revient qu'à environ 100k/sec sur un réseau 100Mbps. Mais j'imagine que le problème est toujours le même - les données mettent beaucoup de temps à arriver, l'application cliente ne reçoit aucun retour pour savoir ce qui se passe, donc elle finit par arriver à expiration. – Malvineous

Répondre

2

Je suppose que vous voulez simplement appeler le service Web de manière asynchrone, afin que votre application ne bloque pas sur l'interface utilisateur pendant que tout se passe. Jetez un oeil à http://msdn.microsoft.com/en-us/library/ms233842.aspx et voir si cela aide.

+0

-1: il s'agit des services Web ASMX, qui sont une technologie héritée. Voir http://msdn.microsoft.com/en-us/library/7bkzywba.aspx et beaucoup d'autres pages. –

+1

@Malvineous utilisez-vous asmx ou WCF? Je peux mettre à jour la réponse avec un lien WCF ... –

+0

J'utilise ASMX (je pense que l'URL du service web se termine par .asmx) parce que c'est ce que l'application est venue avec. Mettre l'appel dans un autre thread ne va probablement pas aider beaucoup, parce que je vais toujours obtenir l'erreur de délai d'attente sur le client. – Malvineous

2

Je vous recommande de décharger la tâche sur SSRS, qui gère les requêtes de longue durée sans problème. Vous pouvez créer un rapport avec votre générateur de rapports, puis utiliser votre application .NET pour appeler les services Web SSRS et exécuter votre rapport, puis exporter les résultats au format Excel (en tant que tableau d'octets). Voir this page pour l'exemple de code à l'aide du service .asmx et this page pour l'appel de SSRS avec WCF.

Vous devez également appeler votre service Web dans un thread distinct pour éviter de bloquer votre interface utilisateur.

6

Nous avions ce scénario d'entreprise exact il y a quelques années, et je vais vous dire ce que nous avons fait.

  1. Essayez de limiter la quantité de données transférées
  2. Si vous transférez n tables, les diviser en n datatables et le transfert d'un datatable à la fois.
  3. Compressez votre jeu de données/datatable avant de transférer. Cela fait un énorme (énorme énorme) impact. De l'autre côté, décompressez le flux d'octets dans un dataset/datatable. N'utilisez pas non plus la compression intégrée de .NET - utilisez SharpZipLib. Cela donne de bien meilleurs résultats.
  4. En outre, vous pouvez effectuer le transfert de manière asynchrone pour empêcher le client de se bloquer.

Nos clients utilisent la solution ci-dessus, sans problème, depuis des années.

+0

Merci pour la suggestion. Normalement, cela fonctionnerait bien, mais dans mon cas particulier, c'est juste une grande table qui doit être transférée de sorte qu'elle ne puisse pas être divisée en tables plus petites. Comme il ne fonctionne qu'à 100k/sec sur un réseau de 100Mbps je ne pense pas que la compression aiderait, et même asynchrone cela prend encore assez de temps pour que l'appel expire :-( – Malvineous

1

Voir "Large Data and Streaming" dans la bibliothèque MSDN. N'utilisez pas les services Web ASMX si vous souhaitez effectuer des transferts de données volumineux.

0

Le problème est commun: vous avez beaucoup de données à retourner à l'utilisateur.

Si vous avez de la chance, vous pouvez vous en sortir en augmentant le délai d'expiration du service Web.Dans le cas contraire, une solution consistant à renvoyer à l'utilisateur des données comportant des pages à la fois répondrait-elle à vos besoins? Dans cette conception, l'appelant serait responsable de spécifier la page de démarrage, et combien de lignes de données par page à votre service Web.

Voir Pagination Queries et Pagination tips

Si toutefois, vous n'êtes pas limité à l'utilisation webservice comme une solution, alors vous pourriez enquêtions offrir des services d'information à vos utilisateurs. Vraiment vaut la peine d'examiner cette option alternative :)

+0

Merci pour la suggestion. les données proviennent d'une vue Oracle, et une grande partie du ralentissement est en cours d'exécution.Même si elle était paginée, chaque page serait très lente (à moins que je garde le curseur Oracle ouvert entre les appels ...) – Malvineous

+0

@Malvineous, vous n'avez pas besoin de garder votre curseur entre les appels. Voir mes liens mis à jour ci-dessus. – Syd

2

Je recommande WCF Data Services (ou peu importe comment il s'appelle maintenant). Vous pouvez exposer un point de terminaison oData qui (si vous avez .NET des deux côtés du service web) vous donne une limitation de requête transparente (le serveur limite le nombre de réponses dans un seul appel et le client effectue automatiquement des requêtes supplémentaires). Il vous donne également une interface de type IQueryable extrêmement flexible.

Questions connexes