C# 本地数据库的事务作用域

C# 本地数据库的事务作用域,c#,sql-server,transactionscope,C#,Sql Server,Transactionscope,我目前正在尝试使用TranactionScope和本地文件数据库(mdf)实现一些端到端测试(E2E)。有趣的是,查询没有回滚,所以我的所有更新/插入都被持久化。我不明白哪里做错了 using (new TransactionScope()) { var newItem1 = new SomeEntity { Id = 4, Remark = "Test 2" }; var newItem2 = new SomeEn

我目前正在尝试使用TranactionScope和本地文件数据库(mdf)实现一些端到端测试(E2E)。有趣的是,查询没有回滚,所以我的所有更新/插入都被持久化。我不明白哪里做错了

        using (new TransactionScope())
        {
            var newItem1 = new SomeEntity { Id = 4, Remark = "Test 2" };
            var newItem2 = new SomeEntity { Id = 5, Remark = "Test 2" };

            var x = new List<SomeEntity> { newItem1, newItem2 };
            _testTvp.SaveSomeEntities(x);

            var result = _test.GetSomeEntity(4);
            Assert.AreEqual(newItem1.Remark, result.Remark);
            result = _test.GetSomeEntity(5);
            Assert.AreEqual(newItem2.Remark, result.Remark);
        }
使用(新TransactionScope())
{
var newItem1=newsomeentity{Id=4,Remark=“Test 2”};
var newItem2=newsomeentity{Id=5,Remark=“Test 2”};
var x=新列表{newItem1,newItem2};
_testTvp.SaveSomeEntities(x);
var result=_test.GetSomeEntity(4);
断言.AreEqual(newItem1.Remark,result.Remark);
结果=_test.GetSomeEntity(5);
断言.AreEqual(newItem2.Remark,result.Remark);
}
我的连接字符串是:


有关更多代码,请参见此处:

没有任何错误。这就是
TransactionScope
的工作原理

如果事务范围内没有发生异常(即 TransactionScope对象的初始化和 它的Dispose方法),然后是作用域所在的事务 允许继续。如果内部确实发生异常 事务范围,它所参与的事务将 被击退


它仅在发生异常时才回滚事务

为什么不尝试使用

    using (SqlConnection sqlConnection = new SqlConnection(connectionString))
                {
                    sqlConnection.Open();
                    using (SqlTransaction sqlTrans = sqlConnection.BeginTransaction())
                    {
                       //put your code here
                    }
                 }

根据您的堆栈,您可能有环境事务:

string connStr = "...; Enlist = false";
using (TransactionScope ts = new TransactionScope())
{
    using (SqlConnection conn1 = new SqlConnection(connStr))
    {
        conn1.Open();
        conn1.EnlistTransaction(Transaction.Current);
    }
}
试试这个:

    using (new scope = new TransactionScope())
    {
        var newItem1 = new SomeEntity { Id = 4, Remark = "Test 2" };
        var newItem2 = new SomeEntity { Id = 5, Remark = "Test 2" };

        var x = new List<SomeEntity> { newItem1, newItem2 };
        _testTvp.SaveSomeEntities(x);

        var result = _test.GetSomeEntity(4);
        Assert.AreEqual(newItem1.Remark, result.Remark);
        result = _test.GetSomeEntity(5);
        Assert.AreEqual(newItem2.Remark, result.Remark);

        //either of the two following:
        Transaction.Current.Rollback();
        scope.Dispose();

    }
使用(新范围=新事务范围())
{
var newItem1=newsomeentity{Id=4,Remark=“Test 2”};
var newItem2=newsomeentity{Id=5,Remark=“Test 2”};
var x=新列表{newItem1,newItem2};
_testTvp.SaveSomeEntities(x);
var result=_test.GetSomeEntity(4);
断言.AreEqual(newItem1.Remark,result.Remark);
结果=_test.GetSomeEntity(5);
断言.AreEqual(newItem2.Remark,result.Remark);
//下列两种情况之一:
Transaction.Current.Rollback();
scope.Dispose();
}

嗯,我想不出到底是什么地方出了问题。可能的解决方案是删除插入的数据。这不是最好的方法,但使用DbTransaction更好。我将尝试使用真正的sql server创建一些测试,看看有什么不同。

但是如果没有完整的事务,将不会提交。。。回滚从未失败过,如果我只是不执行完成。我试图抛出一个异常,但似乎它们对Transaction@RomanKern然后
\u testTvp.SaveSomeEntities(x)
正在提交事务。\u testTvp的类型为:ExecutionTest:IRepository。ExecutionTest是一个没有任何实现的接口。我正在使用代理为这个方法生成执行赌注。拦截器类名为GenericdInterceptor。没有提交某些内容的事务。这种行为真奇怪。也许这取决于数据库引擎。对于这个测试,我使用本地数据库。我可以将数据库移到真正的服务器上,然后再试一次。@RomanKern您可以使用sqlprofiler并调试代码以查看生成的sql吗?您应该逐行调试代码,并查看事务何时提交以及由哪行代码提交。也许它并没有打开任何事务…也许我只是误解了TransactionScope的技术,但只要我记得TransactionScope就永远不会触发BeginTransaction和commit。我的sql代码总是存储过程调用。我必须将事务绑定到特定的DbCommand。这使得代码更加复杂。若我可以从连接中访问事务而不创建新的,那个就好了。您可以查看项目中IRepository的执行堆栈。也许会更清楚,为什么根本没有BeginTransaction,
SaveSomeEntities
做什么?我使用的是IDbConnection。它保证了对多个数据库的最大灵活性。在SqlDbConnection中定义的EnglistTransaction显式。所以我不能用它。如果我将IDbConnection转换为SqlDbConnection,则登记事务对我有效。连接字符串enlist=false/true对事务作用域没有影响我不确定连接是如何定义的。您没有调用Complete方法,这就是您不确定事务被持久化的原因吗?我不想持久化数据。。。测试应该只添加一些处于未提交状态的临时数据。当然,我可以直接从表中删除数据,但回滚是我的第一个选择是的,它们不应该更大,因为您没有调用Complete,但不知道SaveSomeEntities方法在做什么。进一步扩展很复杂。Save SomeEntity是一个惰性的DB调用。。。由类生成:目前它是一个快速而肮脏的实现