Как установить точки сохранения для Linq в SQL и использовать «НЕТ» ExecuteCommand? - PullRequest
1 голос
/ 16 июня 2010
    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 ]

1 голос
/ 16 июня 2010

Я бы посоветовал просто не делать этого. Это не обязательно то, что вы хотите услышать, но особенно при микшировании с TransactionScope точки сохранения не являются хорошей идеей. TransactionScope s может быть вложенным, но первый откат обрекает все , и фиксация происходит только в самой внешней транзакции.

В большинстве сценариев, о которых я могу подумать, лучше очистить данные сначала . Вы можете (и должны) также использовать ограничения для сети безопасности, но если вы нажмете эту сеть безопасности, допустите большие проблемы и откатитесь на все.


Пример вложенных транзакций:

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-транзакцию, поскольку существует внешняя транзакция. Это просто говорит: «Я счастлив». И наоборот, если либо внутренних транзакций отменяется (Dispose() вызывается без Complete()), то транзакция external откатывается немедленно , и эта сделка откажется от любой дополнительной работы. Транзакция external фиксируется, только если транзакция inner не была прервана, и Complete() вызывается во внешней транзакции.

0 голосов
/ 16 июня 2010

Как насчет 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);
...