📄 sqlstateclientmanager.cs
字号:
SqlStateConnection GetConnection(string id, ref bool usePooling) {
SqlStateConnection conn = null;
if (_partitionInfo == null) {
//Debug.Assert(s_partitionManager != null);
//Debug.Assert(_partitionResolver != null);
// _partitionInfo = (SqlPartitionInfo)s_partitionManager.GetPartition(_partitionResolver, id);
_partitionInfo = s_singlePartitionInfo;
}
//Debug.Trace("SessionStatePooling", "Calling GetConnection under " + WindowsIdentity.GetCurrent().Name);
#if DBG
//Debug.Assert(_module._rqChangeImpersonationRefCount != 0,
"SessionStateModule.ChangeImpersonation should have been called before making any call to SQL");
#endif
usePooling = CanUsePooling();
if (usePooling) {
conn = (SqlStateConnection) _partitionInfo.RetrieveResource();
if (conn != null && (conn.Connection.State & ConnectionState.Open) == 0) {
conn.Dispose();
conn = null;
}
}
if (conn == null) {
conn = new SqlStateConnection(_partitionInfo);
}
return conn;
}
void DisposeOrReuseConnection(ref SqlStateConnection conn, bool usePooling) {
try {
if (conn == null) {
return;
}
if (usePooling) {
_partitionInfo.StoreResource(conn);
conn = null;
}
}
finally {
if (conn != null) {
conn.Dispose();
}
}
}
internal static void ThrowSqlConnectionException(SqlConnection conn, Exception e) {
if (s_usePartition) {
throw new HttpException(
SR.GetString(SR.Cant_connect_sql_session_database_partition_resolver,
s_configPartitionResolverType, conn.DataSource, conn.Database));
}
else {
throw new HttpException(
SR.GetString(SR.Cant_connect_sql_session_database),
e);
}
}
SessionStateStoreData DoGet(HttpContext context, String id, bool getExclusive,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actionFlags) {
SqlDataReader reader;
byte [] buf;
MemoryStream stream = null;
SessionStateStoreData item;
bool useGetLockAge = false;
SqlStateConnection conn = null;
SqlCommand cmd = null;
bool usePooling = true;
//Debug.Assert(id.Length <= SessionIDManager.SESSION_ID_LENGTH_LIMIT, "id.Length <= SessionIDManager.SESSION_ID_LENGTH_LIMIT");
//Debug.Assert(context != null, "context != null");
// Set default return values
locked = false;
lockId = null;
lockAge = TimeSpan.Zero;
actionFlags = 0;
buf = null;
reader = null;
conn = GetConnection(id, ref usePooling);
//Debug.Assert(_partitionInfo != null, "_partitionInfo != null");
//Debug.Assert(_partitionInfo.SupportFlags != SupportFlags.Uninitialized, "_partitionInfo.SupportFlags != SupportFlags.Uninitialized");
//
// In general, if we're talking to a SQL 2000 or above, we use LockAge; otherwise we use LockDate.
// Below are the details:
//
// Version 1
// ---------
// In v1, the lockDate is generated and stored in SQL using local time, and we calculate the "lockage"
// (i.e. how long the item is locked) by having the web server read lockDate from SQL and substract it
// from DateTime.Now. But this approach introduced two problems:
// 1. SQL server and web servers need to be in the same time zone.
// 2. Daylight savings problem.
//
// Version 1.1
// -----------
// In v1.1, if using SQL 2000 we fixed the problem by calculating the "lockage" directly in SQL
// so that the SQL server and the web server don't have to be in the same time zone. We also
// use UTC date to store time in SQL so that the Daylight savings problem is solved.
//
// In summary, if using SQL 2000 we made the following changes to the SQL tables:
// i. The column Expires is using now UTC time
// ii. Add new SP TempGetStateItem2 and TempGetStateItemExclusive2 to return a lockage
// instead of a lockDate.
// iii. To support v1 web server, we still need to have TempGetStateItem and
// TempGetStateItemExclusive. However, we modify it a bit so that they use
// UTC time to update Expires column.
//
// If using SQL 7, we decided not to fix the problem, and the SQL scripts for SQL 7 remain pretty much
// the same. That means v1.1 web server will continue to call TempGetStateItem and
// TempGetStateItemExclusive and use v1 way to calculate the "lockage".
//
// Version 2.0
// -----------
// In v2.0 we added some new SP TempGetStateItem3 and TempGetStateItemExclusive3
// because we added a new return value 'actionFlags'. However, the principle remains the same
// that we support lockAge only if talking to SQL 2000.
//
// (When one day MS stops supporting SQL 7 we can remove all the SQL7-specific scripts and
// stop all these craziness.)
//
if ((_partitionInfo.SupportFlags & SupportFlags.GetLockAge) != 0) {
useGetLockAge = true;
}
try {
if (getExclusive) {
cmd = conn.TempGetExclusive;
}
else {
cmd = conn.TempGet;
}
cmd.Parameters[0].Value = id + _partitionInfo.AppSuffix; // @id
cmd.Parameters[1].Value = Convert.DBNull; // @itemShort
cmd.Parameters[2].Value = Convert.DBNull; // @locked
cmd.Parameters[3].Value = Convert.DBNull; // @lockDate or @lockAge
cmd.Parameters[4].Value = Convert.DBNull; // @lockCookie
cmd.Parameters[5].Value = Convert.DBNull; // @actionFlags
try {
reader = cmd.ExecuteReader();
/* If the cmd returned data, we must read it all before getting out params */
if (reader != null) {
try {
if (reader.Read()) {
//Debug.Trace("SqlSessionStateStore", "Sql Get returned long item");
buf = (byte[]) reader[0];
}
}
finally {
reader.Close();
}
}
}
catch (Exception e) {
ThrowSqlConnectionException(cmd.Connection, e);
}
/* Check if value was returned */
if (Convert.IsDBNull(cmd.Parameters[2].Value)) {
//Debug.Trace("SqlSessionStateStore", "Sql Get returned null");
return null;
}
/* Check if item is locked */
//Debug.Assert(!Convert.IsDBNull(cmd.Parameters[3].Value), "!Convert.IsDBNull(cmd.Parameters[3].Value)");
//Debug.Assert(!Convert.IsDBNull(cmd.Parameters[4].Value), "!Convert.IsDBNull(cmd.Parameters[4].Value)");
locked = (bool) cmd.Parameters[2].Value;
lockId = (int) cmd.Parameters[4].Value;
if (locked) {
//Debug.Trace("SqlSessionStateStore", "Sql Get returned item that was locked");
//Debug.Assert(((int)cmd.Parameters[5].Value & (int)SessionStateActions.InitializeItem) == 0,
// "(cmd.Parameters[5].Value & SessionStateActions.InitializeItem) == 0; uninit item shouldn't be locked");
if (useGetLockAge) {
lockAge = new TimeSpan(0, 0, (int) cmd.Parameters[3].Value);
}
else {
DateTime lockDate;
lockDate = (DateTime) cmd.Parameters[3].Value;
lockAge = DateTime.Now - lockDate;
}
//Debug.Trace("SqlSessionStateStore", "LockAge = " + lockAge);
if (lockAge > new TimeSpan(0, 0, 30758400 /* one year */)) {
//Debug.Trace("SqlSessionStateStore", "Lock age is more than 1 year!!!");
lockAge = TimeSpan.Zero;
}
return null;
}
actionFlags = (SessionStateActions) cmd.Parameters[5].Value;
if (buf == null) {
/* Get short item */
//Debug.Assert(!Convert.IsDBNull(cmd.Parameters[1].Value), "!Convert.IsDBNull(cmd.Parameters[1].Value)");
//Debug.Trace("SqlSessionStateStore", "Sql Get returned short item");
buf = (byte[]) cmd.Parameters[1].Value;
//Debug.Assert(buf != null, "buf != null");
}
// Done with the connection.
DisposeOrReuseConnection(ref conn, usePooling);
try {
stream = new MemoryStream(buf);
item = Deserialize(context, stream);
_rqOrigStreamLen = (int) stream.Position;
}
finally {
if (stream != null) {
stream.Close();
}
}
return item;
}
finally {
DisposeOrReuseConnection(ref conn, usePooling);
}
}
public override SessionStateStoreData GetItem(HttpContext context,
String id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actionFlags) {
//Debug.Trace("SqlSessionStateStore", "Calling Sql Get, id=" + id);
//SessionIDManager.CheckIdLength(id, true /* throwOnFail */);
return DoGet(context, id, false, out locked, out lockAge, out lockId, out actionFlags);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context,
String id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actionFlags) {
//Debug.Trace("SqlSessionStateStore", "Calling Sql GetExclusive, id=" + id);
//SessionIDManager.CheckIdLength(id, true /* throwOnFail */);
return DoGet(context, id, true, out locked, out lockAge, out lockId, out actionFlags);
}
// This will deserialize and return an item.
// This version uses the default classes for SessionStateItemCollection, HttpStaticObjectsCollection
// and SessionStateStoreData
private static SessionStateStoreData Deserialize(HttpContext context, Stream stream) {
int timeout;
SessionStateItemCollection sessionItems;
bool hasItems;
bool hasStaticObjects;
HttpStaticObjectsCollection staticObjects;
Byte eof;
//Debug.Assert(context != null);
try {
BinaryReader reader = new BinaryReader(stream);
timeout = reader.ReadInt32();
hasItems = reader.ReadBoolean();
hasStaticObjects = reader.ReadBoolean();
if (hasItems) {
sessionItems = SessionStateItemCollection.Deserialize(reader);
}
else {
sessionItems = new SessionStateItemCollection();
}
if (hasStaticObjects) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -