1
    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 でのみです。セーブポイントで何が起こるか分からないので関数を使いたい!

4

2 に答える 2

1

私は単にそうしないことをお勧めします。必ずしも聞きたいとは限りませんが、特にとミキシングする場合TransactionScope、セーブポイントは良い考えではありません。TransactionScopes はネストできますが、最初のロールバックですべてが台無しになり、コミットは最も外側のトランザクションでのみ発生します。

私が考えることができるほとんどのシナリオでは、最初にデータをサニタイズすることをお勧めします。セーフティ ネットに制約を使用することもできます (またそうする必要があります) が、そのセーフティ ネットにヒットした場合は、大きな問題を想定してすべてをロールバックします。


ネストされたトランザクションの例:

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は、アトミックです。アカウント トランザクション追加して推定残高を更新するか、どちらも更新しません。これが唯一のトランザクションである場合、このメソッドの最後でコミットされます。

ただし、このTransferメソッドでは、別の外部トランザクションを作成します。両方 を実行するか、どちらも実行DebitCreditAccountません。ここでは、外部トランザクションがあるため、内部tran.Complete()(in DebitCreditAccount)は db-transaction をコミットしません。単純に「嬉しい」です。ただし、逆に、内側のトランザクションのいずれかが中止される (Dispose()なしで呼び出されるComplete()) 場合、外側のトランザクションはすぐにロールバックされ、そのトランザクションは追加の作業を拒否します。外部トランザクションは、内部トランザクションが中止されなかった場合にのみコミットされ、外部トランザクション Complete()呼び出されます。

于 2010-06-16T12:25:23.123 に答える
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);
于 2010-06-16T12:05:34.433 に答える