utilisant ASP.NET 2.0 SqlMembershipProvider Pour illustrer problème avec MSSQL 2005.contrôle de connexion ASP.NET et ADO.NET connexion mise en commun
:
1) Créer une application simple ASP.NET avec un System.Web. Contrôle UI.WebControls.Login sur une page. Modifiez Web.config pour utiliser l'authentification par formulaires et System.Web.Security.SqlMembershipProvider.
2) Exécutez l'application Web dans le navigateur et connectez-vous. Fermer le navigateur
3) À l'aide d'un outil SQL (tel que SQL Server Management Studio), exécutez sp_who2 pour voir les connexions. Trouvez SPID pour la connexion utilisée par le SqlMembershipProvider à l'étape 2, et exécuter
kill <the found SPID>
(Suppose mise en commun de connexion est utilisé, ce qui est par défaut).
4) Réexécutez l'application Web dans le navigateur. Essayez de vous reconnecter. Cette fois-ci un SqlException comme ce qui suit est élevé:
[SqlException (0x80131904): A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +925466
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +800118
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +186
System.Data.SqlClient.TdsParserStateObject.ThrowExceptionAndWarning() +13
System.Data.SqlClient.TdsParserStateObject.WriteSni() +682631
System.Data.SqlClient.TdsParserStateObject.WritePacket(Byte flushMode) +265
System.Data.SqlClient.TdsParserStateObject.ExecuteFlush() +51
System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc) +4163
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +1005
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +132
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +122
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) +62
System.Web.Security.SqlMembershipProvider.GetPasswordWithFormat(String username, Boolean updateLastLoginActivityDate, Int32& status, String& password, Int32& passwordFormat, String& passwordSalt, Int32& failedPasswordAttemptCount, Int32& failedPasswordAnswerAttemptCount, Boolean& isApproved, DateTime& lastLoginDate, DateTime& lastActivityDate) +1121
System.Web.Security.SqlMembershipProvider.CheckPassword(String username, String password, Boolean updateLastLoginActivityDate, Boolean failIfNotApproved, String& salt, Int32& passwordFormat) +105
System.Web.Security.SqlMembershipProvider.CheckPassword(String username, String password, Boolean updateLastLoginActivityDate, Boolean failIfNotApproved) +42
System.Web.Security.SqlMembershipProvider.ValidateUser(String username, String password) +83
System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e) +160
System.Web.UI.WebControls.Login.AttemptLogin() +105
System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e) +99
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +35
System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) +115
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +163
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746
Maintenant, je comprends pourquoi cela se passe - à savoir son dû à une connexion mis en commun qui a été tué, et est donc invalide lorsque le contrôle de connexion essaie de réutiliser. La commande de session "kill" est exécutée à l'étape 3 pour simuler ce qui se passerait, par exemple, lorsque vous devez restaurer une base de données. Vous devez supprimer toutes les connexions à une base de données avant de pouvoir la restaurer.
Forcer le redémarrage de l'application Web après la commande kill résout le problème, mais je me demande s'il existe un moyen relativement simple de rendre le processus de connexion plus robuste. Ce serait idéal si d'une manière ou d'une autre, je pouvais attraper cette exception pendant le processus d'authentification, et réessayer le login (puisque ADO.NET semble effacer le pool de connexions après un échec comme celui-ci, je pense que la tentative fonctionnerait).
Je devrais ajouter: désactiver la mise en commun des connexions n'est pas une option viable ici –
Cher dieu, utilisez le langage de balisage intégré! –