im当前使用autoFac在IOC设置中使用EF6。在我的服务中,我像这样注入我的dbcontext:
private readonly CommerceContext _dbContext;
public UserTokenService(CommerceContext dbContext)
{
_dbContext = dbContext;
}
当我更新我的令牌时,随机发生了几个不同的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包含我所有不同的DBSET,并且如下注册:
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);
对该方法的每个调用都是来自不同域的Web API。我几乎卡住了。我自己没有经历过错误,但是我可以在服务器日志中看到它。我唯一能想到的可能性是一次开放的连接太多,这真的很糟糕,因为该网站当前没有很多用户。我是否应该以不同的方式注册我的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:TeamCitybuildAgentwork38cf8b2b27f5e099src#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:TeamCitybuildAgentwork38cf8b2b27f5e099src#UserTokenService.cs:line 79
我发现我的问题是由我为验证身份验证令牌验证的Webapi ActionFilter属性引起的。
在此属性中,我将我的UserTokenService存储在私有变量中,从依赖项索尔佛获得服务。
这是一个非常糟糕的解决方案,因为WebApi ActionFilter属性正在缓存,因此基本上我的服务正在通过使用该属性的每个API请求共享。
解决方案是使用httprequestmessage在Onationexecuting((中提供的范围:
var scope = actionContext.Request.GetDependencyScope();
var tokenService = scope.GetService(typeof(IUserTokenService)) as IUserTokenService;
一个更好的解决方案是使用AUTOFACS实现此处描述的ActionFilterAttribute:
http://autofaccn.readthedocs.io/en/latest/integration/webapi.html#provide-filters-filters-via-dependenty-Inpoction
这使控制器注入您的动作窗。但是在我的情况下,是需要范围服务的更好选择。