这对我来说是一个非常奇怪的问题。关键是我无法在本地环境中重现异常(我有完整的源代码来运行调试,连接仍然是来自远程位置的实时连接)。
我有一个名为IDataAccess
的接口,用于访问我所有控制器中使用的所有sql数据。所以我打算在这里使用单身人士。
问题是我还使用Unity Container将该实例(作为依赖项)注入我的控制器。这是一个使用该接口的控制器:
public AccountController(IDataAccess da){
DataAccess = da;
}
//this instance is used inside the controller
public IDataAccess DataAccess {get;set;}
以下是我配置Unity容器的方法,我有一个单独的类:
public class UnityContainerConfig
{
public static IUnityContainer Uc { get; private set; }
public static void LoadDependencies(IUnityContainer uc = null)
{
Uc = uc ?? new UnityContainer();
Uc.AddNewExtension<Interception>();
//some other not-related registration here
Uc.RegisterType<IDataAccess, DataAccess>(new ContainerControlledLifetimeManager(),
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<UserInfoCacheInterceptionBehavior>(),
new InjectionConstructor(WebConfigurationManager.ConnectionStrings["TestConnection"].ConnectionString,
WebConfigurationManager.ConnectionStrings["loginConnection"].ConnectionString),
new InterceptionBehavior<LoggingInterceptionBehavior>()
);
//other registrations ...
}
}
最后,我调用LoadDependencies
中的UnityConfig.LoadComponents
(我还使用Unity.Mvc5
将Unity与MVC集成),如下所示:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
UnityContainerConfig.LoadDependencies(container);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
在RegisterComponents()
的正确位置调用Application_Start
。
因此,您可以看到我有IDataAccess
的实施名为DataAccess
。这有一个构造函数接受2个字符串(2个连接字符串)(这些是使用InjectionConstructor
注入的)。我还添加了一些截取来拦截IDataAccess
的日志记录和缓存(我认为这部分不应该涉及)。
这是随机抛出的异常(我从记录的文本中复制了它):
6/5/2017 8:40:55 AM - 异常:System.TypeInitializationException:&#39;&lt; Module&gt;&#39;的类型初始值设定项抛出一个例外。 ---&GT; System.AppDomainUnloadedException:尝试访问已卸载的AppDomain。 at .cctor() ---内部异常堆栈跟踪结束--- 在DynamicModule.ns.Wrapped_IDataAccess_bf33a9ed4f92418083f514de204b5b2a.CheckLogin(String userName,String password) 在AsmChecklistSite.ApplicationSignInManager.d__1.MoveNext() ---从抛出异常的先前位置开始的堆栈跟踪结束--- 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 在AsmChecklistSite.Controllers.AccountController.d__15.MoveNext() ---从抛出异常的先前位置开始的堆栈跟踪结束--- 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) 在System.Web.Mvc.Async.AsyncControllerActionInvoker。&lt;&gt; c__DisplayClass37.b__36(IAsyncResult asyncResult) 在System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.b__3d() 在System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters。&lt;&gt; c__DisplayClass46.b__3f() 在System.Web.Mvc.Async.AsyncControllerActionInvoker。&lt;&gt; c__DisplayClass33.b__32(IAsyncResult asyncResult) 在System.Web.Mvc.Async.AsyncControllerActionInvoker。&lt;&gt; c__DisplayClass21。&lt;&gt; c__DisplayClass2b.b__1c() 在System.Web.Mvc.Async.AsyncControllerActionInvoker。&lt;&gt; c__DisplayClass21.b__1e(IAsyncResult asyncResult)
在登录时发生这种情况,CheckLogin
的调用是在Login
的{{1}}操作方法内调用的。
AccountController
就像这样简单:
CheckLogin
这里我使用public async Task<bool> CheckLogin(string userName, string password)
{
password = SomeUtil.Encode(password);
using(var con = new SqlConnection(LoginConnectionString))
{
var i = con.ExecuteScalar<int>("select count(1) from Users where username=@u and password=@p", new { u = userName, p = password });
return i > 0;
}
}
(作为DAL,它扩展了IDbConnection,因此我可以在连接实例上使用扩展方法Dapper
。)
正如我之前所说,我无法在我的本地环境中重现这一点。只有在将站点发布到我的服务器之后,才会随机抛出异常。有时我可以登录确定,甚至在此之后尝试多次。但有时它会因异常而失败(一旦失败,在尝试之后尝试多次尝试仍会失败)。然后在一段时间后,我仍然可以再次登录OK。这真的很奇怪。
我已经没有关于如何发生这种情况的想法。 Unity容器应该是单例(它由ExecuteScalar
类中的静态实例保存,也由UnityContainerConfig
包裹,由单例UnityDependencyResolver
管理) 。 DependencyResolver.Current
也使用IDataAccess
注册。所以我希望它的实例是单例并持久化?我仍然不确定异常消息的实际含义(因此它实际上可能不涉及IDataAccess?)