好吧,这可能很难。asp.net 使用 session 紧密,所以如果 session 存储失败,那么 asp.net 在 session 模块的初始化过程中也会失败。您可以编写自己的会话状态提供程序,它将包装现有的,如果失败,它将返回空的会话项,但很难使用它,因为会话行为可能是不可预测的。
您可以查看内置的SQL 会话状态提供程序,如果您的 SQL 服务器具有复制功能,该提供程序具有故障转移功能。
更新1
这是默认会话提供程序的包装器示例
public class SessionProviderWrapper : SessionStateStoreProviderBase
{
private readonly SessionStateStoreProviderBase _provider;
private static Func<SessionStateStoreProviderBase> _createProvider;
static SessionProvider()
{
_createProvider = InitializerProvider();
}
private static Func<SessionStateStoreProviderBase> InitializerProvider()
{
if (_createProvider != null)
return _createProvider;
var sessionType = "stateserver"; // you can switch to another session provider
Type type;
switch (sessionType)
{
case "inproc":
type = Type.GetType("System.Web.SessionState.InProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
case "sql":
type = Type.GetType("System.Web.SessionState.SqlSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
case "stateserver":
type = Type.GetType("System.Web.SessionState.OutOfProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
default:
throw new ConfigurationErrorsException("Unknow session type: " + sessionType);
}
if (type == null)
{
throw new InvalidOperationException("Failed to find session provider for " + sessionType);
}
_createProvider = GenerateConstructorCall(type);
return _createProvider;
}
private static Func<SessionStateStoreProviderBase> GenerateConstructorCall(Type type)
{
// we are searching for public constructor
var constructor = type.GetConstructors().FirstOrDefault(c => c.GetParameters().Length == 0);
if (constructor == null)
{
// otherwise for internal. SQL session provider has internal constructor, but we don't care
constructor = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Length == 0);
}
var node = Expression.New(constructor);
var lambda = Expression.Lambda<Func<SessionStateStoreProviderBase>>(node, null);
var func = lambda.Compile();
return func;
}
public SessionProvider()
{
var createProvider = InitializerProvider();
_provider = createProvider();
}
public override void Initialize(string name, NameValueCollection config)
{
_provider.Initialize(name, config);
}
public override string Name
{
get { return _provider.Name; }
}
public override string Description
{
get { return _provider.Description; }
}
public override void Dispose()
{
_provider.Dispose();
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return _provider.SetItemExpireCallback(expireCallback);
}
public override void InitializeRequest(HttpContext context)
{
_provider.InitializeRequest(context);
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
out SessionStateActions actions)
{
try
{
return _provider.GetItem(context, id, out locked, out lockAge, out lockId, out actions);
}
catch (Exception ex)
{
locked = false;
lockAge = TimeSpan.Zero;
lockId = null;
actions = SessionStateActions.None;
// log ex
return new SessionStateStoreData(new SessionStateItemCollection(), new HttpStaticObjectsCollection(), 10);
}
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
out SessionStateActions actions)
{
return _provider.GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions);
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
_provider.ReleaseItemExclusive(context, id, lockId);
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
_provider.SetAndReleaseItemExclusive(context, id, item, lockId, newItem);
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
_provider.RemoveItem(context, id, lockId, item);
}
public override void ResetItemTimeout(HttpContext context, string id)
{
_provider.ResetItemTimeout(context, id);
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
return _provider.CreateNewStoreData(context, timeout);
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
_provider.CreateUninitializedItem(context, id, timeout);
}
public override void EndRequest(HttpContext context)
{
_provider.EndRequest(context);
}
}
基本上,您可以像 GetItem 方法一样对每个方法进行 try\catch,如果出现错误,您可以返回空会话对象。如果它在 try\catch 应用程序中失败,它仍然会存在。但是性能会降低,因为每个请求都会在 Get\Release 上抛出几个异常,这些异常将在 catch 部分处理。但无论如何,这些异常会稍微降低性能