AXForum  
Go Back   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Forgotten Your Password?
Register Forum Rules FAQ Members List Today's Posts Search

 
 
Thread Tools Search this Thread Display Modes
Old 08.08.2016, 06:43   #1  
Pandasama is offline
Pandasama
Участник
 
467 / 140 (5) +++++
Join Date: 11.08.2014
Location: Барнаул
Statement, запрос (несколько) с транзакцией
Товарищи, имею нижеописанную проблему.

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

Если я выполняю запрос из Management Studio, я получаю в ответ сообщения вроде
Quote:
1 row affected;
2000 row affected;
3 row affected;
Или если в последней части запроса была какая-либо ошибка, то:
Quote:
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 в первой части.
Old 08.08.2016, 07:04   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,449 / 1792 (66) ++++++++
Join Date: 28.04.2007
Location: Калуга
А нельзя ли объединить все три части в один Statement и выполнить его за один executeUpdate?
Old 08.08.2016, 07:08   #3  
Pandasama is offline
Pandasama
Участник
 
467 / 140 (5) +++++
Join Date: 11.08.2014
Location: Барнаул
Quote:
Originally Posted by S.Kuskov View Post
А нельзя ли объединить все три части в один Statement и выполнить его за один executeUpdate?
Как описано в посте, если я объединяю в один Statement, то при наличии ошибки во второй-третьей части запроса (после первого успешного оператора SELECT) - не вызывает ошибку в statement.executeUpdate(), и Ax продолжает работать дальше, думая что запрос отработал корректно.
Old 08.08.2016, 09:26   #4  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2494 (89) +++++++++
Join Date: 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
This post has been rated by: raz (5), Logger (3), gl00mie (2), Pandasama (1).
Old 08.08.2016, 10:39   #5  
Pandasama is offline
Pandasama
Участник
 
467 / 140 (5) +++++
Join Date: 11.08.2014
Location: Барнаул
Quote:
Originally Posted by AndyD View Post
оберните свои запросы в блок 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();
}
запрос получается вот такой
Code:
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
валидацию он проходит, но в рантайме дает ошибку
Quote:
(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() выполняется без ошибки
Old 30.11.2022, 21:47   #6  
dim-gin is offline
dim-gin
Участник
 
41 / 30 (2) +++
Join Date: 15.04.2014
Location: СПб
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. Хотя в трёшке тот же эффект.

Это норм или что-то где-то надо туда-сюда?
Old 01.12.2022, 01:35   #7  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,719 / 1204 (44) ++++++++
Join Date: 13.01.2004
Blog Entries: 3
Quote:
Originally Posted by dim-gin View Post
Это норм или что-то где-то надо туда-сюда?
Это норм. Документация в этой части не корректная.

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

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

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

 

Similar Threads
Thread Thread Starter Forum Replies Last Post
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

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Рейтинг@Mail.ru
All times are GMT +3. The time now is 19:46.
Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Contacts E-mail, Advertising.