2011-05-17 1 views
0

Je suis en cours d'exécution d'une requête qui renvoie ~ 30.000 lignes d'un C# TableAdapter, et souvent je reçois une erreur comme:Sql Server 2005 Timeouts avec adaptateurs .NET

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. 

at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)\r\n at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData() 
at System.Data.SqlClient.SqlDataReader.get_MetaData() 
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) 
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) 
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) 
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) 
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) 
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)\r\n at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) 
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior) 
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable) 

Si je lance la même requête avec moins les lignes retournées, je ne recevrai pas l'erreur. Et si j'exécute exactement la même requête que le TableAdapter en C# s'exécute dans SSMS moi-même, la requête de 30 000 lignes retourne bien.

Ce qui pourrait causer cela?

Edit: La requête dans SSMS prend environ 7 secondes

+0

Ceci est un message d'erreur typique si une requête frappe le délai d'attente de commande (normalement 30 secondes). Vous devez fournir plus de détails pour votre requête/table/données. – MicSim

+1

Combien de temps faut-il pour que la requête se termine lorsque vous exécutez manuellement? – lincolnk

+0

@lincolnk environ 7 secondes –

Répondre

0

Cela peut poser un problème avec les index. Surtout que vous avez dit que la requête s'exécute dans SSMS mais pas dans le code. Voir cet article qui a plus d'informations (et une bonne lecture de l'OMI):

http://www.sommarskog.se/query-plan-mysteries.html

3

Vous devez prolonger la période de temporisation de la requête pour obtenir des résultats. Comme le jeu de résultats est énorme, la requête peut prendre un certain temps. La plupart expire probablement avant que les résultats ne soient générés

Vous pouvez utiliser la propriété CommandTimeout de SQLCommand pour définir l'expiration du délai. Réglez-le sur une grande période à des fins de test et vérifiez si vous obtenez les résultats ou non

+1

ou le mettre à 0, donc il ne temporise pas – Beth

0

Combien de temps dure la prise requête? Prenez le SQL et exécutez-le directement dans la base de données et à quelle vitesse est-il? Il peut être nécessaire de tourner avec un index ou une autre méthode d'accord si cela prend beaucoup de temps.

Vous pouvez augmenter le délai d'attente, mais pourquoi 30 000 enregistrements ont été renvoyés. Si ce n'est pas un processus d'arrière-plan, la requête doit être configurée pour être paginée afin de renvoyer les enregistrements X à la fois.

Si vous avez besoin absolument 30.000 dossiers:

utilisateur un DataReader, son adaptateur plus rapide et moins de ressources qu'une des données, gardez à l'esprit qu'il utilise une approche avant seulement (maison de feu) à retreival de données.

records Pull en morceaux à la fois, par exemple 1000 extraient, processus, tirer 1000, proceess ...

le délai de déconnexion en .Net Tune la requête pour le faire tourner plus vite

Tenir compte mise en cache si les 30 000 enregistrements si les données ne sont pas trop volatiles

0

Ceci est spéculatif, mais vous pourriez rencontrer une instance de reniflage de paramètres causant des problèmes.

http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/

La solution rapide est d'ajouter des variables locales, copier vos valeurs de paramètres aux variables locales puis utilisez les vars locales dans la requête. De l'article ci-dessus

CREATE PROCEDURE MyProcedure 
    @UserName nvarchar(20) 
AS 

BEGIN 
    DECLARE @myUserName nvarchar(20) 
    SET @myUserName = @UserName 
    -- Insert statements for procedure here 
    SELECT DisplayName, FirstName, LastName 
    FROM dbo.User 
    WHERE UserName = @myUserName 

END 

Plus d'informations sur ce qui se passe réellement ici: http://www.sqlpointers.com/2006/11/parameter-sniffing-stored-procedures.html