C# 为什么';中止交易工作?

C# 为什么';中止交易工作?,c#,.net,compact-database,npoco,C#,.net,Compact Database,Npoco,我正在使用Npco,试图处理事务,我无法使用AbortTransaction方法回滚数据库中的任何内容 public class ItemRepository { private Func<Database> _db; public ItemRepository(Func<Database> db) { _db = db; } Public void Update(){ using (_db().Transaction)

我正在使用Npco,试图处理事务,我无法使用
AbortTransaction
方法回滚数据库中的任何内容

public class ItemRepository
{
  private Func<Database> _db;

  public ItemRepository(Func<Database> db)
  {
        _db = db;
  }

Public void Update(){
    using (_db().Transaction)
    {
        _db().BeginTransaction();
        foreach (var item in itemToUpdate.Items)
        { 
            _db().Insert(item);
            if (SomethingIsNotCorrect())
            {
                _db().AbortTransaction();
            }
        }
    _db().CompleteTransaction();
    }
}}
-------------在建议答案后编辑:

var db = _db();
using (db.Transaction)
{
    db.BeginTransaction();  
    foreach (var item in itemToUpdate.Items)
    {
        db.Insert(item);
        db.Transaction.Commit();
        if (GetNutrientConns(itemToUpdate).Count > 2)
        {
             db.AbortTransaction();
        }
    }  
    db.CompleteTransaction();
}
现在我必须使用db.Transaction.Commit()在数据库中插入一些内容。然后,当尝试运行db.AbortTransaction()时,我收到错误消息:


“此SqlCeTransaction已完成;它不再可用。”

从您的更新中可以清楚地看出问题所在。您正在创建一个工厂函数,该函数实例化并返回一个新的连接/数据上下文,并将其传递到存储库构造函数中。到目前为止还不错

然后,您将继续调用从factory函数获得的新的
数据库
实例上的每个与事务相关的调用,这毫无意义。在构造函数中,使用factory函数实际获取
数据库
实例,并将其存储在字段中。尽可能多地使用它

public class ItemRepository
{
    private Database _db;

    public ItemRepository(Func<Database> dbFactory)
    {
        _db = dbFactory();
    }

    ...
}

最终解决方案更新方法:

var db = _dbFactory();
public void Update() {
try
{
    db.BeginTransaction();
    foreach(item in itemlist)
    {
        db.Insert(item);
    }
    db.CompleteTransaction();
}
catch(Exception)
{
    db.Transaction.Rollback();
}

我不确定异常中是否需要回滚,因为当我使用抛出异常进行测试时,事务会消失。

什么是_db()?不要说它是返回新DB的方法connection@Reniuz,私人功能数据库;在构造函数中设置一次应该是相同的。@daniel\u我以前从未使用过这个库,但我强烈怀疑你应该调用一次,将结果存储在字段或变量中,并重复引用它。实际上,你能在这里向我们展示你的所有代码,它们是调用图的一部分,所以我们不是在猜测吗?请包括构造函数和此处引用的任何字段。这不是构造函数中接受的
数据库
实例。它是一个返回数据库实例的函数。无论它是生成一个新的还是一次又一次地返回同一个,对我们来说都是不透明的(显然对您来说也是如此,因为您在构造函数中接受它)。创建一个类型为
IDatabase
Database
或其他类型的字段,并将
\u db=db()
存储在构造函数中。另外,请将您正在接受的
Func db
参数重命名为
dbFactory
或其他名称,因为这就是原因。或者,OP可以在每个方法的开头调用factory方法,并在整个调用过程中使用返回的实例。这将有助于确保线程安全,因为对
Update
的两个调用不能共享同一个实例。@MikeC这是一个公平的观点。无论哪种方式,每次调用
Update
方法都不应该有多个对工厂函数的调用。@另外,我很抱歉,但这没有帮助。。我需要了解npoco是如何处理事务的。@daniel看起来您根本误解了数据库事务是什么。事务允许您以原子方式对一组数据库交互进行分组,并能够通过提交事务或通过回滚还原事务开始后的所有内容来将它们全部设置为实际。无法回滚已提交的事务。这是毫无意义的,与此无关npoco@daniel_aren您可能希望在不提交的情况下“预览”事务的效果,但这与您选择的数据库中的隔离级别有关,同样,与npoco或您向我们展示的代码无关。
public class ItemRepository
{
    private Func<Database> _dbFactory;

    public ItemRepository(Func<Database> dbFactory)
    {
        _dbFactory = dbFactory;
    }

    public void Update() {
        var db = _dbFactory();

        // Now use db wherever you were using _db()
        ...
    }
}
var db = _dbFactory();
public void Update() {
try
{
    db.BeginTransaction();
    foreach(item in itemlist)
    {
        db.Insert(item);
    }
    db.CompleteTransaction();
}
catch(Exception)
{
    db.Transaction.Rollback();
}