我已经在ASP.NET Core 2.1应用中像这样配置EF 2.1:
services.AddDbContext<TacsDbContext>(
options => options.UseSqlServer(connectionString, sql => sql.EnableRetryOnFailure()),
ServiceLifetime.Transient, ServiceLifetime.Singleton);
每次重启应用后,在生产环境中运行几天后,我都会收到所有请求的消息:
System.Data.SqlClient.SqlException(0x80131904):连接超时 已过期尝试消耗以下内容时超时时间已过 登录前握手确认。这可能是因为 登录前握手失败或服务器无法响应 时间。尝试连接到该服务器所花费的时间 是-[登录前]初始化= 1470;握手= 1; -> System.ComponentModel.Win32Exception(258):等待操作计时
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.AsyncIterator`1.MoveNext(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.FirstOrDefault_[TSource](IAsyncEnumerable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.TaskResultAsyncEnumerable`1.Enumerator.MoveNext(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.AsyncIterator`1.MoveNext(CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteSingletonAsyncQuery[TResult](QueryContext queryContext, Func`2 compiledQuery, IDiagnosticsLogger`1 logger, Type contextType)
at TACS.People.PeopleRepository.GetPersonInformation(String enterpriseId) in D:\a\1\s\TACS.People\PeopleRepository.cs:line 39
at TACS.People.PeopleRepositoryExtensions.EnsurePerson(IPeopleRepository peopleRepository, String enterpriseId) in D:\a\1\s\TACS.People\PeopleRepositoryExtensions.cs:line 13
at TACS.Web.AppCode.Auth.TacsClaimsTransformation.AddPersonId(ClaimsPrincipal principal) in D:\a\1\s\TACS.Web\AppCode\Auth\TacsClaimsTransformation.cs:line 77
at TACS.Web.AppCode.Auth.TacsClaimsTransformation.TransformAsync(ClaimsPrincipal principal) in D:\a\1\s\TACS.Web\AppCode\Auth\TacsClaimsTransformation.cs:line 52
at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
at TACS.Web.Startup.<>c__DisplayClass6_0.<<Configure>b__0>d.MoveNext() in D:\a\1\s\TACS.Web\Startup.cs:line 172
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
ClientConnectionId:89feb963-e494-4f12-94fb-57aa18a2c116
Error Number:-2,State:0,Class:11
似乎打开了太多连接。这是因为我已经使用了瞬态服务寿命吗?
我认为,每当我要访问数据库时,创建新的DbContext是一个好习惯。使用作用域生存期会导致每个请求将使用DbContext的单个实例,并且它看起来像反模式,因为可能会有多个工作单元。