0

我正在使用 npoco,试图处理事务,我无法获得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();
    }
}}

从测试类调用:

_db = () => new Database(String.Format("DataSource={0};Persist Security Info=False;", DbPath),"System.Data.SqlServerCe.4.0");
_itemRepository = new ItemRepository(() => _db());
_itemRepository.Update();

------------- 建议答案后编辑:

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 已完成;它不再可用。”

4

2 回答 2

2

从您的更新中,很清楚问题出在哪里。您正在创建一个工厂函数,该函数实例化并返回一个新的连接/数据上下文,并将其传递给您的存储库构造函数。到目前为止,一切都很好。

然后,您将继续在您从工厂函数获得的新Database实例上调用每个与事务相关的调用,这没有任何意义。在您的构造函数中,使用您的工厂函数实际获取一个Database实例,并将其存储一个字段中。根据需要多次使用它。

public class ItemRepository
{
    private Database _db;

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

    ...
}

更新:正如 Mike C 所指出的,为了进一步限制数据上下文的范围和生命周期,最好存储工厂并创建一个存在于方法Database范围内的实例Update,如下所示:

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()
        ...
    }
}
于 2014-10-29T13:31:44.993 回答
0

最终解决方案更新方法:

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

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

于 2014-10-30T10:28:51.277 回答