Переключение на Главную Страницу Страницы: [1] 2  ОтправитьПечать
Горячая тема (более 10 ответов) Работа с транзакциями (число прочтений - 7140 )
Frog
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 22
Зарегистрирован: 27. Мая 2008
Работа с транзакциями
04. Июня 2008 :: 03:55
Печать  
Доброго дня, утра, вечера, ночи!
Нужна помощь по работе с транзакциями.
Суть задачи: Есть база SQL (нужна для формирования проводок GAAP). Проводки должны формироваться при проведении документа в 1С. По определенным условиям формируется Таблица значений, где в каждой строке содержится информация для создания одной проводки. После этого таблица передается в глобальную процедуру.
Где в рамках одной транзакции должны формироваться проводки, при не удачной попытке создания хотя бы одной проводки из таблицы, транзакция должна откатываться. Вот тут и возникают проблемы.
Алгоритм релизации:
Процедура ПодключениеSQL_GAAP() Экспорт
     глSQLConError=0;
     глDBConnStr = "Provider=SQLOLEDB.1;Data Source=dl2;Initial Catalog=GAAP;Integrated Security=SSPI;";
     Попытка
           глSQLCon.Open(глDBConnStr);
           глSQLConError=0;
     Исключение
           глSQLConError=1;
     КонецПопытки;
КонецПроцедуры

//Функции формирования проводок
--------------------------
//Флаг=1 принять транзакцию
//Флаг=0 откатить транзакцию
Функция глЗафиксироватьОткатитьТранзакцию(ИмяТранзакции,Флаг=1,СтрокаЗапроса="") Экспорт
     Если Число(глSQLCon.State)=0 Тогда
         ПодключениеSQL_GAAP();
           Если Число(глSQLCon.State)=0 Тогда
                 Сообщить("Нет связи с базой GAAP!");
                 Возврат 0;
           КонецЕсли;
     КонецЕсли;
     Сообщ="";
     Если Флаг=1 Тогда
           СтрокаЗапроса=СтрокаЗапроса+"COMMIT TRANSACTION "+ИмяТранзакции;
           Сообщ="принятия";
     Иначе
           СтрокаЗапроса=СтрокаЗапроса+"ROLLBACK TRANSACTION "+ИмяТранзакции;      
           Сообщ="отката";
     КонецЕсли;       
    Попытка
           Сообщить(СтрокаЗапроса);
       глSQLRec = глSQLCon.Execute(СтрокаЗапроса);
           Возврат 1;
    Исключение
       Сообщить("Ошибка "+Сообщ+" транзакции "+ОписаниеОшибки());                  
           Возврат 0;
    КонецПопытки;
     
КонецФункции


//*******************************************
     
Функция глФормироватьПроводкиGAAP(ТЗ,ВыводитьПредупреждение=1) Экспорт
     Если Число(глSQLCon.State)=0 Тогда
         ПодключениеSQL_GAAP();
           Если Число(глSQLCon.State)=0 Тогда
                 Сообщить("Нет связи с базой GAAP!");
                 Возврат 0;
           КонецЕсли;
     КонецЕсли;
     Если ТЗ.КоличествоСтрок()>0 Тогда
           ИмяТранзакции="PROV";
           //Открываем транзакцию, блокируем таблицы до завершения транзакций
           СтрокаЗапроса="BEGIN TRANSACTION "+ИмяТранзакции+"
           |";
         Попытка
             глSQLRec = глSQLCon.Execute(СтрокаЗапроса);                  
           Исключение
                 Сообщить(СтрокаЗапроса);
             Сообщить("Ошибка при открытии транзакции "+ОписаниеОшибки());
                 Возврат 0;
         КонецПопытки;
     КонецЕсли;
     ТЗ.ВыбратьСтроки();
     Пока ТЗ.ПолучитьСтроку()=1 Цикл
           СтрокаЗапроса=СтрокаЗапроса+"
         | SET DATEFORMAT dmy;
         | EXEC InsertJournalEntries_Kor
         | "+?(ПустоеЗначение(ТЗ.Flag)=1,"NULL",ТЗ.Flag)+",
         | "+?(ПустоеЗначение(ТЗ.AccountGAAP_D)=1,"NULL",ТЗ.AccountGAAP_D)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_D1)=1,"NULL",ТЗ.RefObj_D1)+",
         | "+?(ПустоеЗначение(ТЗ.RefObj_D2)=1,"NULL",ТЗ.RefObj_D2)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_D3)=1,"NULL",ТЗ.RefObj_D3)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_D4)=1,"NULL",ТЗ.RefObj_D4)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_D5)=1,"NULL",ТЗ.RefObj_D5)+",
         | "+?(ПустоеЗначение(ТЗ.AccountGAAP_K)=1,"NULL",ТЗ.AccountGAAP_K)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_K1)=1,"NULL",ТЗ.RefObj_K1)+",
         | "+?(ПустоеЗначение(ТЗ.RefObj_K2)=1,"NULL",ТЗ.RefObj_K2)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_K3)=1,"NULL",ТЗ.RefObj_K3)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_K4)=1,"NULL",ТЗ.RefObj_K4)+",
           | "+?(ПустоеЗначение(ТЗ.RefObj_K5)=1,"NULL",ТЗ.RefObj_K5)+",
           | "+?(ПустоеЗначение(ТЗ.CurrencyNumber)=1,"NULL",ТЗ.CurrencyNumber)+",
         | "+ТЗ.CurrencyNumber+",
         | "+ТЗ.Summa_Currency+",
         | "+ТЗ.Summa+",
         | '"+СокрЛП(ЗначениеВСтрокуВнутр(ТЗ.Doc_ID))+"',
         | '"+ТЗ.Date_In+"',
         |
         | "+?(ПустоеЗначение(ТЗ.Kurs)=1,"NULL",ТЗ.Kurs)+",
         | '"+ТекущаяИБКод()+"',
         | '"+Пользователь.Наименование+"',
         | 0
           |";
         Попытка
                 Сообщить(СтрокаЗапроса);
             глSQLRec = глSQLCon.Execute(СтрокаЗапроса);                  
         Исключение
             Сообщить("Ошибка при формировании проводки GAAP "+ОписаниеОшибки());
                 глЗафиксироватьОткатитьТранзакцию(ИмяТранзакции,0);                  
                 Возврат 0;
         КонецПопытки;
     КонецЦикла;
     
     Если глЗафиксироватьОткатитьТранзакцию(ИмяТранзакции,1)=1 Тогда
           Возврат 1;
           //Докумет проведен
     Иначе
           //Документ не проведен
     КонецЕсли;


КонецФункции

Проблемы: После первого прохода цикла и выполнения Execute при запуске Stored Procedure InsertJournalEntries_Kor 1C теряет коннект с открытой транзакцией, в результате я не могу ни принять транзакцию ни откатить её, ни записать следующую строку, так как таблица блокируется и 1С вылетает по таймауту.
Причем если сделать все одной строкой, а в самом конце запустить Execute, то все выполняется. Но тут возникают проблемы с откатом. Хочеться контролировать откаты на уровне 1С. Может кто знает как выполнять несколько Execute в рамках одной транзакции.
Спасибо.
  
Наверх
 
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: Работа с транзакциями
Ответ #1 - 04. Июня 2008 :: 03:59
Печать  
А подключение у тебя через oledb зачем? У меня через ODBC вроде всё работает
  
Наверх
ICQ  
IP записан
 
Frog
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 22
Зарегистрирован: 27. Мая 2008
Re: Работа с транзакциями
Ответ #2 - 04. Июня 2008 :: 04:02
Печать  
Nick писал(а) 04. Июня 2008 :: 03:59:
А подключение у тебя через oledb зачем? У меня через ODBC вроде всё работает

Сейчас попробую.
  
Наверх
 
IP записан
 
Frog
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 22
Зарегистрирован: 27. Мая 2008
Re: Работа с транзакциями
Ответ #3 - 04. Июня 2008 :: 04:18
Печать  
Nick писал(а) 04. Июня 2008 :: 03:59:
А подключение у тебя через oledb зачем? У меня через ODBC вроде всё работает

Не могу найти как правильно формат задать
глDBConnStr = "Provider=SQLODBC.1;Data Source=dl2;Initial Catalog=GAAP;Integrated Security=SSPI;";
так не работает
  
Наверх
 
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: Работа с транзакциями
Ответ #4 - 04. Июня 2008 :: 04:23
Печать  
Driver={SQL Server};Server=ИмяСервераСмехatabase=БазаДанных;Uid=Пользователь;Pwd=Пароль;
  
Наверх
ICQ  
IP записан
 
Frog
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 22
Зарегистрирован: 27. Мая 2008
Re: Работа с транзакциями
Ответ #5 - 04. Июня 2008 :: 04:26
Печать  
Nick писал(а) 04. Июня 2008 :: 04:23:
Driver={SQL Server};Server=ИмяСервераСмехatabase=БазаДанных;Uid=Пользователь;Pwd=Пароль;

а если нужно под доменным пользователем, обязательно указывать пароль и логин?
  
Наверх
 
IP записан
 
Nick
God Member
*****
Отсутствует



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: Работа с транзакциями
Ответ #6 - 04. Июня 2008 :: 04:31
Печать  
Frog писал(а) 04. Июня 2008 :: 04:26:
Nick писал(а) 04. Июня 2008 :: 04:23:
Driver={SQL Server};Server=ИмяСервераСмехatabase=БазаДанных;Uid=Пользователь;Pwd=Пароль;

а если нужно под доменным пользователем, обязательно указывать пароль и логин?


Тогда не указывай пользователя
  
Наверх
ICQ  
IP записан
 
Frog
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 22
Зарегистрирован: 27. Мая 2008
Re: Работа с транзакциями
Ответ #7 - 04. Июня 2008 :: 05:17
Печать  
При втором проходе вылетает ошибка:
Ошибка при формировании проводки GAAP Microsoft OLE DB Provider for ODBC Drivers: [Microsoft][ODBC SQL Server Driver]Timeout expired

которая отрабатывает на исключение, которое в свою очередь бытается откатить транзакцию, на что получает ошибку

Ошибка отката транзакции Microsoft OLE DB Provider for ODBC Drivers: [Microsoft][ODBC SQL Server Driver][SQL Server]The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.

т.е фактически то же самое что и при Оле дб.
строка подключения
глDBConnStr ="Driver={SQL Server};Server=dl2;Database=GAAP;";
  
Наверх
 
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Работа с транзакциями
Ответ #8 - 04. Июня 2008 :: 07:44
Печать  
А если пользовать методы BeginTrans, CommitTrans, RollbackTrans объекта ADODB.Connection?  Озадачен
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Работа с транзакциями
Ответ #9 - 04. Июня 2008 :: 07:52
Печать  
1. почему не юзается 1С++ Очень довольный
2. можно поля таблицы определить с помощью default если так важно не иметь null но и не мудохаться с ним
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Работа с транзакциями
Ответ #10 - 04. Июня 2008 :: 07:57
Печать  
О!
А что если использовать транзакции самой 1С?
Если в обработке проведения формировать СВОЮ таблицу для проводок В РОДНОЙ БАЗЕ 1С?
А потом либо триггером либо еще как делать инсерт одним запросом?
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
Frog
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 22
Зарегистрирован: 27. Мая 2008
Re: Работа с транзакциями
Ответ #11 - 05. Июня 2008 :: 00:30
Печать  
Проблему решил следующим образом. Выполняю всего один Execute, в который передаю строку со всеми данными

SET XACT_ABORT ON - откатывает транзакции в случае если даже в одной операции возникает ошибка,
по дефолту стоит OFF. В принципе можно и на исключения сделать проверяя @Error, но с абортом кодаменьше Улыбка.
Вопрос конечно остался открытым, но время для сдачи задачи поджимает некогда копаться. Если кто-то что то нароет буду очень благодарен. Всем спасибо кто пытался помочь.

BEGIN TRANSACTION PROV

SELECT TOP 1 ''
FROM GAAP.dbo.GAAP WITH (TABLOCKX,HOLDLOCK)

SELECT TOP 1 ''
FROM GAAP.dbo.GAAP_DAY WITH (TABLOCKX,HOLDLOCK)


SET DATEFORMAT dmy;
EXEC InsertJournalEntries_Kor
1, 99, 1, 5377, 364, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 840, 59.92, 59.92,
'{"O","0","0","32550","0","0","    595790CEN"}', '04.06.08', 'Начисление резерва по продажнику',
23.7473, 'CEN', 'Administrator', 0


SET DATEFORMAT dmy;
EXEC InsertJournalEntries_Kor
1, 98, 1, 5377, 364, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 59.92, 59.92,
'{"O","0","0","32550","0","0","    595790CEN"}', '04.06.08', 'Начисление резерва по продажнику',
23.7473, 'CEN', 'Administrator', 0
     

SET DATEFORMAT dmy;
EXEC InsertJournalEntries_Kor
1, 97, 1, 5377, 364, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 840, 59.92, 59.92,
'{"O","0","0","32550","0","0","    595790CEN"}', '04.06.08', 'Начисление резерва по продажнику',
23.7473, 'CEN', 'Administrator', 0


COMMIT TRANSACTION PROV

SELECT [RecId], [Flag], [AccountGAAP_D], [RefObj_D1], [RefObj_D2], [RefObj_D3], [RefObj_D4], [RefObj_D5], [AccountGAAP_K], [RefObj_K1], [RefObj_K2], [RefObj_K3], [RefObj_K4], [RefObj_K5], [Currency], [Summa_Currency], [Summa], [Doc_ID], [Date_In], [Comments], [Kurs], [Application], [UserName], [IsStorno], [InserStamp]
FROM [GAAP].[dbo].[GAAP]
  
Наверх
 
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Работа с транзакциями
Ответ #12 - 05. Июня 2008 :: 08:30
Печать  
По-моему у меня очень просто и элегантно
Готов спорить до хрипоты  Смех
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
Frog
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 22
Зарегистрирован: 27. Мая 2008
Re: Работа с транзакциями
Ответ #13 - 07. Июня 2008 :: 06:51
Печать  
Цитата:
По-моему у меня очень просто и элегантно
Готов спорить до хрипоты  Смех


Вариант такой не подходит. База 1С уже сейчас занимает 12 гигов, поэтому и было решено вынести все за рамки 1С.

Пробовал сделать через BeginTrans(), CommitTrans(), RollbackTrans(). BeginTrans() отрабатывает, после Execute выполняю CommitTrans(). Пишет что нет активных транзакций. Перечитал кучу мукулатуры, говорят, что работает если поддерживает провайдер, пробовал подключаться кучей способов
     глDBConnStr = "Provider=SQLOLEDB.1;Data Source=dl2;Initial Catalog=GAAP;Integrated Security=SSPI;";
     глDBConnStr = "Driver={SQL Server};Provider=SQLOLEDB.2;Data Source=dl2;Initial Catalog=GAAP;Integrated Security=SSPI;";
     глDBConnStr ="Driver={SQL Server};Provider=MSDASQL;Server=dl2;Database=GAAP;";
так и не смог выполнить пакет процедур в рамках одной транзакции, возможно при подключении нужно указывать какаие то параметры, но какие точно не нашел.

При способе который реализовл и который работает, так же возникли проблемы. Если в рамках транзакции возникает ошибка, то ADO не выдает ошибку, в результате, у меня получается, что документ в любом случае проводится. Пытался вытащить ошибку через Errors:
Описание:
Содержит коллекцию объектов Error. Любая инструкция, использующая объекты ADO, может сгенерировать одну или более ошибок провайдера. Когда происходит ошибка, в эту коллекцию могут быть помещены один или более объектов Error. Если следующая подобная инструкция также сгенерирует ошибку, коллекция будет очищена и заполнена заново. Каждый объект Error представляет определённую ошибку провайдера, но не ошибку ADO (ошибки ADO подвергаются механизму обработки исключительных ситуаций). Используйте метод Clear, чтобы вручную очистить коллекцию Errors. Некоторые свойства и методы возвращают предупреждения, которые появляются как объекты Error в коллекции Errors, при этом не останавливая выполнение программы. Перед тем, как вы вызываете методы Resync, UpdateBatch или CancelBatch объекта Recordset, метод Open объекта Connection, или устанавливаете свойство Filter объекта Recordset, вызовите метод Clear коллекции Errors. После этого вы можете прочитать свойство Count коллекции Errors, чтобы проверить возвращенные предупреждения.

Но я не могу прочитать свойство Count , потому что оно пустое. Пытался сделать через переменную:
set @Err=1

if @Err=0
begin
   set @comp=1
   select @comp as Complete
   COMMIT TRANSACTION PROV
end
else
Begin
select @comp as Complete
ROLLBACK TRANSACTION PROV
End

Но после выполнения рекордсет пустой, короче меня постигла полная ж.... 4-й день пытаюсь как-нибудь сделать, если и получается то не так как нужно. В 1С же как то делают, значит можно, но вот как.
  
Наверх
 
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Работа с транзакциями
Ответ #14 - 07. Июня 2008 :: 21:01
Печать  
Хм... ну а кто мешает после переноса удалять из таблицы данные? Просто типо буфера...
Я говорю что основной плюс - обеспечение целостности данных с помощью самой 1С без гимора абсолютно
Если документ провелся корректно - данные гарантированно будут в таблице (насколько кривые зависит от тебя)
Ферштейн?
И кто сказал что после 12 гиг заканчивается жизнь?
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 
ОтправитьПечать