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

EF Core使用Azure AD SQL认证时调用SqlBulkCopy的事务报错如何解决

问题根本原因

你调用_context.Database.GetDbConnection()返回的是System.Data.Common.DbConnection抽象基类,它的BeginTransaction()方法返回值是基类DbTransaction,无法直接隐式转换为SQL Server专属的SqlTransaction类型,该报错和你使用的Azure AD身份认证逻辑没有关联。

正确修改步骤

  1. 由于你的EF Core配置明确使用SqlServer驱动,运行时获取到的DbConnection实际类型就是Microsoft.Data.SqlClient.SqlConnection,做显式强转即可解决类型转换报错。
  2. 不要用using包裹从EF上下文获取的连接实例,EF会自行管理连接的生命周期,提前手动释放会导致后续上下文操作抛出连接已销毁的异常。
  3. 优化异常处理逻辑,避免重复关闭连接、遗漏异常分支的问题。

修改后的可运行代码

private int WorkitemsToDb(List<AdoWorkitem> list )
{
    try
    {
        // 强转为SQL Server专属连接类型
        var connection = (Microsoft.Data.SqlClient.SqlConnection)_context.Database.GetDbConnection();
        // 连接已被EF打开时无需重复打开,避免报错
        if (connection.State != System.Data.ConnectionState.Open)
        {
            connection.Open();
        }
        // 强转后BeginTransaction方法直接返回SqlTransaction类型
        using var transaction = connection.BeginTransaction();
        using var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction);
        
        bulkCopy.BatchSize = 100;
        bulkCopy.DestinationTableName = "dbo.Person";
        try
        {
            bulkCopy.WriteToServer(list.AsDataTable());
            transaction.Commit();
            return list.Count;
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
        // 不需要手动关闭连接,EF会在上下文释放时自动处理
    }
    catch (Exception ex)
    {
        // 按需添加异常日志记录逻辑
        throw;
    }
}

额外注意事项

  • 你启动类中的DbContext配置存在冗余:有注释掉的重复给azureConnection.AccessToken赋值的逻辑,还有用.Result阻塞调用异步方法GetAuthenticationResultAsync的操作,建议改为异步初始化或者使用EF Core 6自带的Azure AD认证配置,避免触发线程死锁。
  • 如果后续有兼容多数据库的需求,可以补充类型判断逻辑避免强转报错,当前SqlServer场景下强转操作是安全的。

内容的提问来源于stack exchange,提问作者Sandeep Thomas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 03:00:05