AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 08.08.2016, 06:43   #1  
Pandasama is offline
Pandasama
Участник
 
457 / 137 (5) +++++
Регистрация: 11.08.2014
Адрес: Барнаул
Statement, запрос (несколько) с транзакцией
Товарищи, имею нижеописанную проблему.

Есть sql-запрос, который я вызываю из Ax обычным способом (Connection, Statement)
Запрос состоит из трех частей, завернутых в одну транзакцию (транзакцию внутри запроса, через SQL-операторы BEGIN TRANSACTION, COMMIT TRANSACTION) - 1я часть это некоторый SELECT, потом некоторый INSERT, и третья - некоторый UPDATE.

Если я выполняю запрос из Management Studio, я получаю в ответ сообщения вроде
Цитата:
1 row affected;
2000 row affected;
3 row affected;
Или если в последней части запроса была какая-либо ошибка, то:
Цитата:
1 row affected;
2000 row affected;
ошибка такая-то
После чего транзакция, конечно, откатывается.

Однако, когда я вызываю запрос из Ax с помощью
Statement.executeUpdate(query)
то в случае наличия ошибки в третьей (или во второй) части запроса - я об этом никак не узнаю. executeUpdate возвращает 0, getLastError, getLastErrorText - возвращают 0, будто бы операция успешно выполнена (т.к. успешно выполнился первый запрос в транзакции).

Можно ли как-то в такой ситуации получить из Statement корректный отчет о выполнении запроса или добиться, чтобы он кидал ошибку в такой ситуации?

Рабочим сейчас является следующий вариант:
X++:
Connection.ttsbegin()
Statement.executeUpdate(query1);
Statement.executeUpdate(query2);
Statement.executeUpdate(query3);
Connection.ttsCommit()
Из запроса убраны операторы "BEGIN TRANSACTION", "COMMIT TRANSACTION"
Текст запроса разбит на 3 части, каждая из который вызывается отдельно внутри транзакции, организованной классом Connection. Если в одной из частей запроса происходит ошибка, то ttsCommit не вызывается - и все три запроса откатываются.

Но у этого подхода есть один крупный недостаток: т.к. запросы выполняются отдельно, то, например, в третьем запросе я не вижу переменных, которые я DECLARE в первой части.
Старый 08.08.2016, 07:04   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
А нельзя ли объединить все три части в один Statement и выполнить его за один executeUpdate?
Старый 08.08.2016, 07:08   #3  
Pandasama is offline
Pandasama
Участник
 
457 / 137 (5) +++++
Регистрация: 11.08.2014
Адрес: Барнаул
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
А нельзя ли объединить все три части в один Statement и выполнить его за один executeUpdate?
Как описано в посте, если я объединяю в один Statement, то при наличии ошибки во второй-третьей части запроса (после первого успешного оператора SELECT) - не вызывает ошибку в statement.executeUpdate(), и Ax продолжает работать дальше, думая что запрос отработал корректно.
Старый 08.08.2016, 09:26   #4  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
оберните свои запросы в блок try/catch внутри T-SQL

X++:
begin try
    begin tran;
    --  
    commit tran;
end try
begin catch
    rollback tran;
    throw;
end catch
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: raz (5), Logger (3), gl00mie (2), Pandasama (1).
Старый 08.08.2016, 10:39   #5  
Pandasama is offline
Pandasama
Участник
 
457 / 137 (5) +++++
Регистрация: 11.08.2014
Адрес: Барнаул
Цитата:
Сообщение от AndyD Посмотреть сообщение
оберните свои запросы в блок try/catch внутри T-SQL
Не помогло

Вот тестовый пример, аналогичный описываемой задаче:
X++:
public server static void testSQL()
{
    Set                                 permissionSet               = new Set(Types::Class);
    Connection                          connection;
    Statement                           statement;
    str                                 query;
    TestTable3798                       testTable; //test table (SaveDataPerCompany = No) with one field str[10] named Field1
    ;

    query += "BEGIN TRY \n";
    query += "BEGIN TRANSACTION; \n";
    query += "SELECT TOP 1  * FROM CustTable; \n";
    query += "INSERT INTO TESTTABLE3798 (Field1, RecId) VALUES ('test', 123456); \n" ;
    query += "SELECT TOP 1 * FROM SYSTEMSEQUENCES WHERE NAME = -1; \n"; //query with error
    query += "COMMIT TRANSACTION; \n";
    query += "END TRY \n";
    query += "BEGIN CATCH \n";
    query += "ROLLBACK TRANSACTION; \n";
    query += "THROW; \n";
    query += "END CATCH \n";
    
    connection = new Connection();
    statement = connection.createStatement();
    permissionSet.add(new SqlStatementExecutePermission(query));
    CodeAccessPermission::assertMultiple(permissionSet);
    statement.executeUpdate(query);
    CodeAccessPermission::revertAssert();
}
запрос получается вот такой
Код:
BEGIN TRY 
BEGIN TRANSACTION;
SELECT TOP 1 * FROM CustTable; 
INSERT INTO TESTTABLE3798 (Field1, RecId) VALUES ('test', 123456); 
SELECT TOP 1 * FROM SYSTEMSEQUENCES WHERE NAME = -1; 
COMMIT TRANSACTION; 
END TRY 
BEGIN CATCH 
ROLLBACK TRANSACTION; 
THROW;
END CATCH
валидацию он проходит, но в рантайме дает ошибку
Цитата:
(1 row(s) affected)

(1 row(s) affected)

(0 row(s) affected)
Msg 245, Level 16, State 1, Line 5
Conversion failed when converting the nvarchar value 'Event' to data type int.
в указанном выше X++ statement.updateQuery() выполняется без ошибки
Старый 30.11.2022, 21:47   #6  
dim-gin is offline
dim-gin
Участник
 
41 / 30 (2) +++
Регистрация: 15.04.2014
Адрес: СПб
Sorry, подниму здесь простой вопрос, чтобы не создавать новую тему.

Недавно обнаружил, что Statement.executeUpdate не возвращает ничего для простого update. Хотя в документации про return value сказано "An updated row count; otherwise, 0 (zero) for SQL statements that return nothing."

X++:
server static void test()
{
    ResultSet   rs;
    str         sQuery;
    int         qtyUpdated;
    ;

    // так, параметры вывода сообщений
    sQuery = "SELECT CASE WHEN (512 & @@OPTIONS) = 512 THEN 'ON' ELSE 'OFF' END AS a1";
    new SQLStatementExecutePermission(sQuery).assert();
    rs = new Connection().createStatement().executeQuery(sQuery);
    if (rs.next())
        info(rs.getString(1));
    CodeAccessPermission::revertAssert();

    sQuery = "update [dbo].[TestTbl] set RecVersion = RecVersion+1;";
    new SQLStatementExecutePermission(sQuery).assert();
    // проверим, что никто не грохнул запись, пока мы мялись, как школьники у борделя
    qtyUpdated = new Connection().createStatement().executeUpdate(sQuery);
    info(int2str(qtyUpdated));
    CodeAccessPermission::revertAssert();
}
При этом фактическое обновление данных происходит, и транзакция фиксируется.
DAX2009 на ss2012r2, всё стоковое с последними хотфиксами и kb. Хотя в трёшке тот же эффект.

Это норм или что-то где-то надо туда-сюда?
Старый 01.12.2022, 01:35   #7  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от dim-gin Посмотреть сообщение
Это норм или что-то где-то надо туда-сюда?
Это норм. Документация в этой части не корректная.

То число, которое возвращает executeUpdate() - это признак успеха или ошибки

0 - выполнено успешно
число - произошла ошибка

Собственно, это же работа через ODBC, а драйвер ODBC просто не умеет возвращать количество обработанных строк. Вне зависимости от версии Axapta
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: dim-gin (1), Logger (3).
Теги
error, executeupdate, sql, statement, transact sql, transaction

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
dynamicsaxhints: Select statement on field Blog bot DAX Blogs 0 22.03.2016 09:11
emeadaxsupport: AX 2012 R3 for Retail - Clear Statement Greyed Out Blog bot DAX Blogs 0 01.05.2015 20:16
emeadaxsupport: Using Post Inventory along with Calculate and Post Statement in AX 2012 Retail Blog bot DAX Blogs 0 10.03.2015 02:16
emeadaxsupport: Oversettlement error when posting a Retail statement in AX 2012 R2 Blog bot DAX Blogs 0 27.09.2013 06:16
dynamicsaxtraining: Select statement patterns Blog bot DAX Blogs 10 20.08.2010 14:01
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 00:51.