为什么AbortTransaction不起作用?

时间:2014-10-29 12:58:19

标签: c# .net compact-database npoco

我正在使用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中插入一些内容。然后在尝试运行db.AbortTransaction()时收到错误消息:

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

2 个答案:

答案 0 :(得分:2)

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

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

public class ItemRepository
{
    private Database _db;

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

    ...
}

更新:正如Mike C所指出的,为了进一步限制datacontext的范围和生命周期,最好存储工厂并创建一个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()
        ...
    }
}

答案 1 :(得分:0)

最终解决方案更新方法:

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

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