Skip to content

Commit 2599986

Browse files
committed
Added a database comparison at the end of session recovery that issues a "use <database>" command if the client and server's notion of the current database differs.
1 parent 73f2480 commit 2599986

2 files changed

Lines changed: 350 additions & 113 deletions

File tree

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,7 +2314,46 @@ private void CompleteLogin(bool enlistOK) // @TODO: Rename as per guidelines
23142314
_currentSessionData._encrypted = isEncrypted;
23152315
}
23162316

2317+
// After successful session recovery, ensure that both the client and
2318+
// server agree on the current database. The recovery data carries the
2319+
// database the session was using before the connection dropped. If the
2320+
// server's login response (ENV_CHANGE) set a different database — or
2321+
// omitted the token entirely — we must issue a USE command to realign
2322+
// the server and then update CurrentDatabase to match.
2323+
string recoveredDatabase = null;
2324+
if (_recoverySessionData != null)
2325+
{
2326+
recoveredDatabase = _recoverySessionData._database
2327+
?? _recoverySessionData._initialDatabase;
2328+
}
2329+
23172330
_recoverySessionData = null;
2331+
2332+
if (recoveredDatabase != null
2333+
&& !string.Equals(CurrentDatabase, recoveredDatabase, StringComparison.OrdinalIgnoreCase))
2334+
{
2335+
// The server is not on the expected database. Force it there.
2336+
string safeName = SqlConnection.FixupDatabaseTransactionName(recoveredDatabase);
2337+
_parser._physicalStateObj.SniContext = SniContext.Snix_Login;
2338+
Task executeTask = _parser.TdsExecuteSQLBatch(
2339+
$"USE {safeName}",
2340+
ConnectionOptions.ConnectTimeout,
2341+
notificationRequest: null,
2342+
_parser._physicalStateObj,
2343+
sync: true);
2344+
Debug.Assert(executeTask == null, "Shouldn't get a task when doing sync writes");
2345+
_parser.Run(
2346+
RunBehavior.UntilDone,
2347+
cmdHandler: null,
2348+
dataStream: null,
2349+
bulkCopyHandler: null,
2350+
_parser._physicalStateObj);
2351+
_parser._physicalStateObj.SniContext = SniContext.Snix_Login;
2352+
2353+
// The USE command triggers an ENV_CHANGE that updates CurrentDatabase,
2354+
// but set it explicitly in case the response is unexpected.
2355+
CurrentDatabase = recoveredDatabase;
2356+
}
23182357
}
23192358

23202359
Debug.Assert(SniContext.Snix_Login == Parser._physicalStateObj.SniContext,

0 commit comments

Comments
 (0)