如何将Linq的Savepoints设置为SQL并使用“NO”ExecuteCommand?

时间:2010-06-16 12:00:08

标签: c# linq-to-sql transactions savepoints

    TransactionScope TransactionABC = new TransactionScope();
    try
    {
        context.Connection.Open();
        {
            context.ExecuteCommand("insert into test (test) values (1)")
            context.SubmitChanges();
                    context.ExecuteCommand("savepoint test");

            context.ExecuteCommand("insert into test (test) values (2)")
            context.SubmitChanges();

                    context.ExecuteCommand("rollback to test");
            }
    TransactionABC.Complete();
    TransactionABC.Dispose();

            }
   catch (Exception ec)
    {
    MessageBox.Show(" ", ec.Message);
    }
   finally
    {
        context.Connection.Close();
    }

它可以工作,但只能使用ExecuteCommand。我想使用一个函数,因为我无法看到保存点中发生了什么!

2 个答案:

答案 0 :(得分:1)

我建议不要这样做。它不一定是你想要听到的,但是当与TransactionScope混合时,尤其是,保存点并不是一个好主意。 TransactionScope可以嵌套,但第一次回滚会导致所有,而提交只发生在最外层的事务中。

在我能想到的大多数情况下,最好先清理数据 。您可以(也应该)使用安全网的约束,但是如果您点击那个安全网,那么就要承担大问题并回滚所有内容。


嵌套事务的示例:

public void DebitCreditAccount(int accountId, decimal amount, string reference)
{
  using(var tran = new TransactionScope())
  {
    // confirm account exists, and update estimated balance
    var acc = db.Accounts.Single(a => a.Id == accountId);
    acc.BalanceEstimate += amount;
    // add a transaction (this defines the **real** balance)
    db.AccountTransactions.InsertOnSubmit(
         new AccountTransaction {
                 AccountId = accountId, Amount = amount,
                 Code = amount >= 0 ? "C" : "D",
                 Reference = reference });
    db.SubmitChanges();
    tran.Complete();
  }
}
public void Transfer(int fromAccountId, int toAccountId,
           decimal amount, string reference)
{
  using(var tran = new TransactionScope())
  {
    DebitCreditAccount(fromAccountId, -amount, reference);
    DebitCreditAccount(toAccountId, amount, reference);
    tran.Complete();
  }
}

在上文中,DebitCreditAccount是原子的 - 我们会添加帐户 - 交易更新估算余额,或者两者都不添加。如果这是 only 事务,那么它将在此方法结束时提交。

但是,在Transfer方法中,我们创建了另一个外部事务;我们要么 DebitCreditAccount,要么 。此处,内部tran.Complete()(在DebitCreditAccount不提交db-transaction,因为存在外部事务。它只是说“我很开心”。但是,相反,如果内部事务的 中止(Dispose()调用没有Complete()),则外部事务将回滚立即,该交易将拒绝任何额外的工作。仅当没有内部事务中止,并且在外部事务上调用 Complete()时,才会提交外部事务。

答案 1 :(得分:0)

ExecuteQuery怎么样?

使用DataContext.ExecuteQuery,您可以像在ExecuteCommand中一样将文本发送到数据库中 - 但是您可以从该文本中获取查询结果。

IEnumerable<int> results = ExecuteQuery<int>(@"
DECLARE @Table TABLE(Id int)
INSERT INTO @Table SELECT {0}
INSERT INTO @Table SELECT {1}
SELECT Id FROM Table", 101, -101);


IEnumerable<Customer> results = ExecuteQuery<Customer>( @"
Rollback transaction
SELECT *
FROM Customer
WHERE ID = {0}", myId);