C# 在DI环境中使用时出现奇怪且难以调试的错误
Im目前在使用Autofac的IOC设置中使用EF6。 在我的服务中,我将DbContext注入如下:C# 在DI环境中使用时出现奇怪且难以调试的错误,c#,asp.net-mvc,entity-framework,dependency-injection,autofac,C#,Asp.net Mvc,Entity Framework,Dependency Injection,Autofac,Im目前在使用Autofac的IOC设置中使用EF6。 在我的服务中,我将DbContext注入如下: private readonly CommerceContext _dbContext; public UserTokenService(CommerceContext dbContext) { _dbContext = dbContext; } var builder = new ContainerBuilder(); builde
private readonly CommerceContext _dbContext;
public UserTokenService(CommerceContext dbContext)
{
_dbContext = dbContext;
}
var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterModule(new AutofacWebTypesModule());
builder.RegisterAssemblyTypes(typeof(CommerceContext).Assembly)
.Where(t => t.Name.EndsWith("Context"))
.InstancePerRequest();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces()
.InstancePerRequest();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
var scope = actionContext.Request.GetDependencyScope();
var tokenService = scope.GetService(typeof(IUserTokenService)) as IUserTokenService;
当我更新我的令牌时,随机出现两个不同的SQL错误
我的ApiController:
private readonly IUserTokenService _tokenService;
public UsersApiController(IUserTokenService tokenService)
{
this._tokenService = tokenService;
}
[RequireHttps]
[System.Web.Http.HttpGet]
[System.Web.Http.Route("api/users/validatetoken")]
public IHttpActionResult ValidateToken(Guid tokenId)
{
var falseObj = new
{
IsValid = false,
Email = string.Empty
};
var token = _tokenService.Get(tokenId);
if (token == null) return Ok(falseObj);
if (token.IsExpired) return Ok(falseObj);
var user = _userService.Find(token.UserId);
if (user == null) return Ok(falseObj);
_tokenService.Update(token);
}
我的TokenService获取方法:
public UserToken Get(Guid token)
{
return _dbContext.UserTokens.FirstOrDefault(x => x.Token == token);
}
我的TokenService更新方法:
public void Update(UserToken token)
{
token.ExpiresAt = DateTime.UtcNow.AddHours(1);
_dbContext.SaveChanges();
}
_dbContext包含我的所有不同数据库集,注册方式如下:
private readonly CommerceContext _dbContext;
public UserTokenService(CommerceContext dbContext)
{
_dbContext = dbContext;
}
var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterModule(new AutofacWebTypesModule());
builder.RegisterAssemblyTypes(typeof(CommerceContext).Assembly)
.Where(t => t.Name.EndsWith("Context"))
.InstancePerRequest();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces()
.InstancePerRequest();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
var scope = actionContext.Request.GetDependencyScope();
var tokenService = scope.GetService(typeof(IUserTokenService)) as IUserTokenService;
对该方法的每次调用都是来自不同域的web api。
我几乎被卡住了。
我自己没有经历过这个错误,但我可以在服务器日志中看到它。
我能想到的唯一可能性是,一次打开的连接太多,这将非常糟糕,因为该网站目前没有太多用户。
我是否应该以不同的方式注册DbContext、拥有多个DbContext或完全不同的东西
不同的错误:
System.Web.HttpUnhandledException (0x80004005): The underlying provider failed on Open. ---> System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.InvalidOperationException: The connection was not closed. The connection's current state is connecting.
at System.Data.ProviderBase.DbConnectionClosedConnecting.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection connection, DbInterceptionContext interceptionContext)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0()
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at System.Data.Entity.Core.EntityClient.EntityConnection.Open()
--- End of inner exception stack trace ---
at System.Data.Entity.Core.EntityClient.EntityConnection.Open()
at System.Data.Entity.Core.Objects.ObjectContext.EnsureConnection(Boolean shouldMonitorTransactions)
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at #.UserTokenService.Update(UserToken token) in E:\TeamCity\buildAgent\work\38cf8b2b27f5e099\src\#\UserTokenService.cs:line 79
System.Web.HttpUnhandledException (0x80004005): An error occurred while starting a transaction on the provider connection. See the inner exception for details. ---> System.Data.Entity.Core.EntityException: An error occurred while starting a transaction on the provider connection. See the inner exception for details. ---> System.InvalidOperationException: SqlConnection does not support parallel transactions.
at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName, Boolean shouldReconnect)
at System.Data.SqlClient.SqlConnection.BeginTransaction(IsolationLevel iso, String transactionName)
at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.BeginTransaction(DbConnection connection, BeginTransactionInterceptionContext interceptionContext)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at System.Data.Entity.Core.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
--- End of inner exception stack trace ---
at System.Data.Entity.Core.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.Entity.Core.EntityClient.EntityConnection.BeginTransaction()
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at #.UserTokenService.Update(UserToken token) in E:\TeamCity\buildAgent\work\38cf8b2b27f5e099\src\#\UserTokenService.cs:line 79
System.Web.HttpUnhandledException(0x80004005):基础提供程序在打开时失败。-->System.Data.Entity.Core.EntityException:基础提供程序在打开时失败。-->System.InvalidOperationException:连接未关闭。连接的当前状态为“正在连接”。
位于System.Data.ProviderBase.DbConnectionClosedConnection.TryOpenConnection(DbConnection outerConnection、DbConnectionFactory connectionFactory、TaskCompletionSource`1重试,DbConnectionOptions用户选项)
位于System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1重试)
位于System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1重试)
在System.Data.SqlClient.SqlConnection.Open()处
在System.Data.Entity.Infrastructure.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget,Action`2 operation,TInterceptionContext interceptionContext,Action`3 executing,Action`3 executed)
位于System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection连接,DbInterceptionContext interceptionContext)
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.c__DisplayClass1.b__0()中
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1操作)中
在System.Data.Entity.Core.EntityClient.EntityConnection.Open()中
---内部异常堆栈跟踪的结束---
在System.Data.Entity.Core.EntityClient.EntityConnection.Open()中
位于System.Data.Entity.Core.Objects.ObjectContext.EnsureReconnection(布尔值shouldMonitorTransactions)
在System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 Func,IDBEcutionStrategy executionStrategy,Boolean startLocalTransaction,Boolean releaseConnectionOnSuccess)
位于System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions选项、IDBEcutionStrategy executionStrategy、Boolean startLocalTransaction)
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1操作)中
位于System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions选项,布尔值executeInExistingTransaction)
位于System.Data.Entity.Internal.InternalContext.SaveChanges()处
在E:\TeamCity\buildAgent\work\38cf8b2b272f5e099\src\\UserTokenService.cs中的#.UserTokenService.Update(UserToken-token)处:第79行
System.Web.HttpUnhandledException(0x80004005):在提供程序连接上启动事务时出错。有关详细信息,请参见内部异常。-->System.Data.Entity.Core.EntityException:在提供程序连接上启动事务时出错。有关详细信息,请参见内部异常。-->System.InvalidOperationException:SqlConnection不支持并行事务。
位于System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso,String transactionName,Boolean shouldReconnect)
位于System.Data.SqlClient.SqlConnection.BeginTransaction(IsolationLevel iso,String transactionName)
位于System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel IsolationLevel)
在System.Data.Entity.Infrastructure.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget目标,Func`3操作,TInterceptionContext拦截Context,操作`3执行,操作`3执行)
位于System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.BeginTransaction(DbConnection连接,BeginTransactionInterceptionContext拦截上下文)
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1操作)中
位于System.Data.Entity.Core.EntityClient.EntityConnection.BeginDbTransaction(隔离级别隔离级别)
---内部异常堆栈跟踪的结束---
位于System.Data.Entity.Core.EntityClient.EntityConnection.BeginDbTransaction(隔离级别隔离级别)
位于System.Data.Entity.Core.EntityClient.EntityConnection.BeginTransaction()处
在System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 Func,IDBEcutionStrategy executionStrategy,Boolean startLocalTransaction,Boolean releaseConnectionOnSuccess)
位于System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions选项、IDBEcutionStrategy executionStrategy、Boolean startLocalTransaction)
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1操作)中
位于System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions选项,布尔值executeInExistingTransaction)
位于System.Data.Entity.Internal.InternalContext.SaveChanges()处
在E:\TeamCity\buildAgent\work\38cf8b2b272f5e099\src\\UserTokenService.cs中的#.UserTokenService.Update(UserToken-token)处:第79行
我发现我的问题是由我用来验证身份验证令牌的WebApi ActionFilter属性引起的
在这个属性中,我将UserTokenService存储在一个私有变量中,从DependencyResolver获取服务
这是一个非常糟糕的解决方案,因为WebApi ActionFilter属性