ef core dbcontext在service中使用构造函数注入
public class ReportService : IReportService { public ReportService(ApplicationDbContext context) { _context = context; } private ApplicationDbContext _context; }
调用时候偶尔会出现错误,肯定不是偶然~肯定有那里出错了
An unhandled exception occurred while processing the request. InvalidOperationException: The connection was not closed. The connection's current state is connecting. System.Data.ProviderBase.DbConnectionClosedConnecting.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions) Stack Query Cookies Headers InvalidOperationException: The connection was not closed. The connection's current state is connecting. System.Data.ProviderBase.DbConnectionClosedConnecting.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource<DbConnectionInternal> retry, DbConnectionOptions userOptions) System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource<DbConnectionInternal> retry) System.Data.SqlClient.SqlConnection.Open() Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(bool errorsExpected) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+Enumerator.BufferlessMoveNext(bool buffer) Microsoft.EntityFrameworkCore.Storage.Internal.SqlServerExecutionStrategy.Execute<TState, TResult>(TState state, Func<DbContext, TState, TResult> operation, Func<DbContext, TState, ExecutionResult<TResult>> verifySucceeded) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+Enumerator.MoveNext() Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.GetResult<TResult>(IEnumerable<ValueBuffer> valueBuffers, bool throwOnNullResult) lambda_method(Closure , QueryContext ) Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass17_1.<CompileQueryCore>b__0(QueryContext qc) System.Linq.Queryable.Any<TSource>(IQueryable<TSource> source) Silver.CreditReport.Controllers.HomeController+<Index>d__4.MoveNext() in HomeController.cs
连接未关闭,这什么鬼?构造函数注入不会自动释放?
An unhandled exception occurred while processing the request. SqlException: 服务器无法继续执行该事务。说明: 3400000006。 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, bool breakConnection, Action<Action> wrapCloseInAction) Stack Query Cookies Headers SqlException: 服务器无法继续执行该事务。说明: 3400000006。 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, bool breakConnection, Action<Action> wrapCloseInAction) System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, bool breakConnection, Action<Action> wrapCloseInAction) System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, bool callerHasConnectionLock, bool asyncClose) System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, out bool dataReady) System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() System.Data.SqlClient.SqlDataReader.get_MetaData() System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, string resetOptionsString) System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, bool async, int timeout, out Task task, bool asyncWrite, SqlDataReader ds) System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, bool returnStream, TaskCompletionSource<object> completion, int timeout, out Task task, bool asyncWrite, string method) System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) System.Data.Common.DbCommand.ExecuteReader() Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary<string, object> parameterValues) Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary<string, object> parameterValues) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+Enumerator.BufferlessMoveNext(bool buffer) Microsoft.EntityFrameworkCore.Storage.Internal.SqlServerExecutionStrategy.Execute<TState, TResult>(TState state, Func<DbContext, TState, TResult> operation, Func<DbContext, TState, ExecutionResult<TResult>> verifySucceeded) Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+Enumerator.MoveNext() Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider+ExceptionInterceptor+EnumeratorExceptionInterceptor.MoveNext() AspNetCore._Views_Home_Index_cshtml+<ExecuteAsync>d__28.MoveNext() in Index.cshtml
Startup 中是如何注册 ApplicationDbContext 的?
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
asp.net core 2.0 默认就是ServiceLifetime.Scoped
这应该没问题吧?
本机测试,win7+vs2017+sql server 2014
@远扬: 注册没问题,是否可以提供一下对应的 LINQ 部分的代码?
@远扬: 这个问题不是 EF Core 本身的问题,EF Core 会在每次 LINQ 查询( 比如 ToListAsync() )时打开并关闭连接,怀疑可能在代码中的某个地方打开了 EF Core 所关联的数据库连接而没有及时关闭
@dudu:
public IQueryable<ReportListViewModel> GetList() { var data = (from c in _context.Report from d in _context.Investigation where d.Id == c.InvestigationId from e in _context.Order where e.Id == d.OrderId select new ReportListViewModel { Id = c.Id, CreateTime = c.CreateTime, IsOverdue = c.IsOverdue, Name = d.Name, OverdueDate = c.CreateTime, PhoneNumber = d.PhoneNumber, ReportNo = e.OrderNo, IdentityId = d.IdentityId }).OrderByDescending(c => c.CreateTime); return data; }
我直接返回IQueryable<model>到View
@远扬: 在哪里进行了 ToList() 或 ToListAsync() 操作?建议提供一下相关代码
@dudu:
public async Task<IActionResult> Index() {
return View(_reportService.GetList()); }
没有做ToList()或者ToListAsync()操作直接给视图
使用ToList()或者ToListAsync()也会出现这个错误~试过了
@远扬: 注册 ReportService 时用的是哪种 ServiceLifetime ?
@dudu: 使用autofac自动注册
public class DefaultModule : Module { protected override void Load(ContainerBuilder builder) { var baseType = typeof(IDependency); var assemblys = AppDomain.CurrentDomain.GetAssemblies().ToList(); builder.RegisterAssemblyTypes(assemblys.ToArray()) .Where(t => baseType.IsAssignableFrom(t) && t != baseType) .AsImplementedInterfaces() .InstancePerLifetimeScope();
base.Load(builder); } }
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddRouting(opt => opt.LowercaseUrls = true); services.AddMvc(); var builder = new ContainerBuilder(); builder.RegisterModule<DefaultModule>(); builder.Populate(services); ApplicationContainer = builder.Build(); return new AutofacServiceProvider(ApplicationContainer); }
@远扬: 知道了,问题应该出在你将 IQueryable 作为 ViewModel 传递给了视图,建议将 ReportService.GetList() 方法的返回值类型改为 IList 或 IEnumerable
@dudu: 发现在action传递数据给视图做ToList()或者ToListAsync()操作返回给视图会出现
Exception: Unable to cast object of type 'System.Data.ProviderBase.DbConnectionClosedConnecting' to type 'System.Data.SqlClient.SqlInternalConnectionTds'.
@远扬: 不要在视图中 ToList( )或者 ToListAsync()
@dudu:
在MVC5+EF6这样使用不会出错的
@dudu: 如果一个action同时返回ViewBag和ViewModel,都是涉及到数据库读取,是不是使用异步才不会出错.
@远扬: 推荐一个参考材料,其他帮不上了:https://stackoverflow.com/q/41217906/5989202