ADO.NET, транзакции и QueryAnalizer

НЕ СКАЖУ
Дата: 11.11.2004 08:15:56
QueryAnalizer тоже обычная программа, которая написана толи с применением ADO, толи с ODBC. ВВодим в ней строку запроса с серверной транзакцией, и все OK.
Как в ней это реализовано? Мы ведь не можем через ADO.NET выполнить запрос с серверной транзакцией, а только с клиентской.
hDrummer
Дата: 11.11.2004 09:31:19
М.б. какие-то хитрости майкрософтовские, а лучше об этом спросить в ГФ.
Kilroy
Дата: 11.11.2004 09:43:06
В принципе транзакция всегда серверная, начать ее можно
либо написав соотв. TSQL и отправив его саморучно на выполнение,
либо вызвав некий метод класса или API функцию, который отправит тот же
begin transaction на выполнение.
Поэтому в свойство CommandText SqlCommand'а пишем
"begin transaction .......... и т. д." и вперед
НЕ СКАЖУ
Дата: 12.11.2004 01:05:21
Kilroy
В принципе транзакция всегда серверная, начать ее можно
либо написав соотв. TSQL и отправив его саморучно на выполнение,
либо вызвав некий метод класса или API функцию, который отправит тот же
begin transaction на выполнение.
Поэтому в свойство CommandText SqlCommand'а пишем
"begin transaction .......... и т. д." и вперед

Так получится использовать только BEGIN TRAN и COMMIT TRAN, мы не сможем использовать болле сложные транзакции.
Т.е. так можно:
static void Main(string[] args)
		{
			SqlConnection conn=new SqlConnection(@"Database=Cars;Integrated Security=true");
			SqlCommand cmd=conn.CreateCommand();
			cmd.CommandText=   @"BEGIN TRAN
                               INSERT INTO CUSTOMERS(CUSTID,FIRSTNAME,LASTNAME)
                               VALUES(8,'Alex','AlexLast');
                               COMMIT TRAN";
            
			conn.Open();
			
			Console.WriteLine(cmd.ExecuteNonQuery().ToString());
		    
conn.Close();
conn.Dispose();
		}
А так нет:
static void Main(string[] args)
		{
			SqlConnection conn=new SqlConnection(@"Database=Cars;Integrated Security=true");
			SqlCommand cmd=conn.CreateCommand();
			cmd.CommandText=   @"BEGIN TRAN
                               INSERT INTO CUSTOMERS(CUSTID,FIRSTNAME,LASTNAME)
                               VALUES(8,'Alex','AlexLast');
                               IF @@ERROR<>0
                               ROLLBACK TRAN
                               COMMIT TRAN";
            
			conn.Open();
			
			Console.WriteLine(cmd.ExecuteNonQuery().ToString());
		    
conn.Close();
conn.Dispose();
		}
Что-то происходит не то и возникает исключение соединения, а что я не очень понял.
А какой смысл использовать транзакцию T-SQL, если ты не можешь в коде T-SQL ее откатить.
gerss
Дата: 12.11.2004 11:09:13
НЕ СКАЖУ

IF @@ERROR<>0
ROLLBACK TRAN
COMMIT TRAN


Вот тут-то собака и порылась. Если @@ERROR <> 0, то у тебя последовательно должны выполниться и rollback, и commit. То есть транзакция сначала откатывается (и заканчивается), а потом ты пытаешься ее же закоммитить.

Наверное, стоит сделать так:
if @@error <> 0
  rollback tran
else
  commit tran

Таким образом, если ошибка - rollback, иначе - commit, транзакция будет завершена только 1 раз и ошибки должны пропасть.

Сергей
кузя
Дата: 12.11.2004 13:12:41
ошибки уровня 11 и выше будут вызывать SqlException. нужно еще дополнительно использовать try-catch. ошибки уровня выше 19 приводят к закрытию соединения.
НЕ СКАЖУ
Дата: 12.11.2004 21:52:45
Ясно, в чем ошибка.
кузя
ошибки уровня 11 и выше будут вызывать SqlException. нужно еще дополнительно использовать try-catch. ошибки уровня выше 19 приводят к закрытию соединения.

Про какие уровни ты говоришь? Да, и хочется понять в чем разница между клиентской и серверной транзакцией. Может где почитать про это можно?
Alexey Kudinov
Дата: 12.11.2004 22:18:33
НЕ СКАЖУ
Ясно, в чем ошибка.
кузя
ошибки уровня 11 и выше будут вызывать SqlException. нужно еще дополнительно использовать try-catch. ошибки уровня выше 19 приводят к закрытию соединения.

Про какие уровни ты говоришь? Да, и хочется понять в чем разница между клиентской и серверной транзакцией. Может где почитать про это можно?

1 кузя говорит про error severity в MSSQL (читайте BOL Error Message Severity Levels)

2 Серверная транзакция: для MSSQL Server-а существует только одно понятие транзакции: то, что находится, между командами BEGIN TRAN... END TRAN (ROLLBACK TRAN) Понятие IMPLICIT TRANSACTIONS для простоты опустим. В BOL подробно описана работа с транзакциями (см. Controlling Transactions)

3 "Клиентская транзакция": то, что подразумевается под "клиентской транзакцией" может включать в себя все, что угодно и зависит от реализации клиента. Откат/подтверждение состояния каких-то объектов, запись в файл, информирование пользователя и т.п.
кузя
Дата: 12.11.2004 23:24:16
немного дополню п.3 Alexey Kudinov

для "клиентских" транзакций выполняется, как правило два доп. батча
на trans=conn.BeginTransaction();
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGIN TRANSACTION

и на trans.Commit();
COMMIT TRANSACTION
или на trans.Rollback();
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION

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

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

---
если принятие решений делается по принципу - была ошибка, то откатить транзакцию (как в твоем примере) - в этом случае проще и быстрее выполнить "серверную" транзакцию.
НЕ СКАЖУ
Дата: 12.11.2004 23:24:56
Alexey Kudinov

3 "Клиентская транзакция": то, что подразумевается под "клиентской транзакцией" может включать в себя все, что угодно и зависит от реализации клиента. Откат/подтверждение состояния каких-то объектов, запись в файл, информирование пользователя и т.п.

Как она(клиентская транзакция) работает? Я где-то читал(не помню про какие транзакции), что создается контекст(объект) на каждую операцию, потом, если что-то случается, то все объекты откатываются. Это тот случай? Или в ADO.NET это совсем по другому? Или клиентские транзакции на клиенте ADO.NET тоже самое тоже самое, что и серверные?