为什么当 Enlist=False 时,Sqlserver 会在事务中登记?

Why is Sqlserver enlisting in transaction when Enlist=False?

使用 entity Framework 5 (5.0.4) 和本地 SQL 服务器,为什么以下代码没有在数据库中创建一行?

注意连接字符串包含Enlist=False

using System;
using System.Transactions;
using Microsoft.EntityFrameworkCore;

namespace EfTransaction
{
    public class Program
    {
        public static void Main()
        {
            var scope = new TransactionScope();
            var ctx = new MyDbContext();
            var eObj = new MyEntityObject { Name = "My New Object" };

            ctx.Set<MyEntityObject>().Add(eObj);
            
            ctx.SaveChanges();
            
            scope.Dispose();

            Console.WriteLine("Done");
        }
    }
    
    public class MyDbContext : DbContext
    {
        public DbSet<MyEntityObject> MyObjects { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(
                "Server=.;Initial Catalog=MyDb;User Id=sa;Password=hunter2;Integrated Security=false;MultipleActiveResultSets=true;Enlist=False;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<MyEntityObject>().HasKey(x => x.Name);
        }
    }
    
    public class MyEntityObject
    {
        public string Name { get; set; }
    }
}

您需要 scope.Complete(); 来提交交易。另外,我强烈推荐使用 TransactionScopeusing 块,让它负责处理而不是显式调用 Dispose

顺便说一句,Enlist 连接字符串关键字控制分布式事务中的检测和登记,而不是本地事务。

SqlConnection 连接字符串参数控制 System.Transaction SqlConnection 的自动登记。但是 EF Core 检查并加入环境事务。

IE EF 不依赖 ADO.NET DbConnection 来检测和登记环境事务。您可以使用嵌套的 TransactionScope 抑制环境事务:

using (var noTran = new TransactionScope(TransactionScopeOption.Suppress))
{
    using var db = new Db();
    //. . .
    noTran.Complete();
}