You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6中DI注册Insight.Database自动接口运行报错问题

问题描述

在WebApi项目的依赖注入(DI)容器中注册Insight.Database自动接口,初始实现代码如下:

var dataString = builder.Configuration.GetConnectionString("DefaultConnection");

SqlInsightDbProvider.RegisterProvider();
var connection = new SqlConnection(dataString);
builder.Services.AddTransient(thing => connection.AsParallel<IUserData>());
builder.Services.AddTransient(thing => connection.AsParallel<IRoleData>());

控制器中调用注入的接口时抛出异常,无对应公开文档说明,该实现逻辑与其他正常运行的项目代码结构一致,首次异常信息如下:

无法将类型为“Insight.Database.Providers.ProfiledDbConnection”的对象强制转换为类型“System.Data.SqlClient.SqlConnection”
后续补充的异常堆栈指向Insight.Database自动接口代理生成环节的连接类型转换逻辑。

故障原因
  • 注册代码中提前创建了全局唯一的SqlConnection实例,所有DI解析操作都复用这同一个连接对象。数据库连接是有状态资源,并发场景下单连接多线程复用本身就会触发状态错乱、连接池占用等问题。
  • Insight.Database的AsParallel<T>()方法会对传入的原生数据库连接做代理包装,第一次调用后传入的连接实例会被转换为Insight内部封装的ProfiledDbConnection类型,后续重复对这个已经被包装过的连接调用AsParallel<T>()时,内部逻辑会尝试将包装后的连接强转回原生SqlConnection类型,直接触发类型转换异常。如果项目中仅注册单个数据库接口,只会触发一次AsParallel<T>()调用,不会触发重复包装问题,这也是相同代码结构在其他单接口注册项目中可以正常运行的原因。
修复方案

调整DI注册逻辑,将连接创建过程放到服务解析的工厂委托内部,每次解析服务时生成新的连接实例再做接口代理,不要全局复用单个连接对象。修复后代码如下:

var dataString = builder.Configuration.GetConnectionString("DefaultConnection");
SqlInsightDbProvider.RegisterProvider();

builder.Services.AddTransient<IUserData>(_ => 
{
    var conn = new SqlConnection(dataString);
    return conn.AsParallel<IUserData>();
});
builder.Services.AddTransient<IRoleData>(_ => 
{
    var conn = new SqlConnection(dataString);
    return conn.AsParallel<IRoleData>();
});
  • 优化建议:可以直接引入官方DI扩展包Insight.Database.DependencyInjection,实现自动批量注册数据库接口,由扩展包自动处理连接生命周期,避免手动注册出现的生命周期配置错误。
  • 注意:数据库连接不要配置为单例生命周期,使用Transient生命周期匹配WebApi请求场景即可,连接使用完成后会被自动释放回归ADO.NET连接池,不会产生连接泄漏问题。

内容的提问来源于stack exchange,提问作者Rich Bryant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:12:22