06.12.2013, 00:10 | #1 |
Banned
|
forUpdate перед ttsbegin
Вы так программируете?
X++: while select forUpdate myTable { ttsBegin; myTable.MyField = 'something'; myTable.update(); ttsCommit; } Потратил сегодня вечер анализируя это так как пакистанец (неплохой программист с Mерседесом) написал именно так. Внешней TTS нет. X++: void update() { SalesTable salesTable; SalesLine salesLine; ; Global::startLengthyOperation(); while select forupdate salesTable { select firstonly forupdate salesLine where salesLine.SalesId == salesTable.SalesId && salesLine.LineNum == 1; if (salesLine.RecId != 0) { salesLine.SalesForecastPricingManager = MultiRepTable::getSalesForecastPricingManager( salesLine.ItemId, salesTable); ttsbegin; salesLine.doUpdate(); salesTable.SalesForecastPricingManager = salesLine.SalesForecastPricingManager; salesTable.doUpdate(); ttscommit; } } Global::endLengthyOperation(); } |
|
06.12.2013, 00:14 | #2 |
Banned
|
Есть неплохой разбор в статье
https://community.dynamics.com/ax/b/...c-locking.aspx Но автор не все рассмотрел. Вот мои комментарии к статье своим собратьям на мерседесах. Цитата:
What normally I use in the most cases from version AX 4.0 and the author did not mention about that way.
while select myTable { ttsBegin; myTable.selectForUpdate(true); myTable.MyField = 'something'; myTable.update(); ttsCommit; } In versions 2.5 and 3.0 I even declared a second table buffer myTable_upd to select for update every record individually while the first buffer myTable was just for getting records and checking conditions. I might be wrong but despite a fact many developers use that new and probably modern style (i.e. select for update before ttsbegin) I am still concern 1. That article did not highlight how SQL Server behaves if locks or exceptions happened. Normally in T-SQL (in which X++ are translated) we use BEGIN { TRAN | TRANSACTION } before to select for update. 2. I have never seen official examples of code (MSDN, MCT materials) including AX 2012 where that modern style is used. Am I too old and not creative enough anymore? |
|
06.12.2013, 01:58 | #3 |
Banned
|
Один мой товарищ мне написал "Компилятор распознаёт это правильно, почему бы и нет".
Но компилятор и даже BP много чего пропускает. Был бы он умный не было бы runtime errors. И скажем сертифицирование такой код не пройдет и более или менее нормален на конкретном End User. Так как работает только при оптимистической конкуренции. Что же это за код который сломается при изменении настроек на таблице или в приложении? Я лично не могу такой код писать. И есть у меня подозрения что SQL server не любит такое просто его никто не слышит. Была бы моя власть я бы не пропускал такой код. Те кто программировал до AX 4.0 вряд ли так программируют. У меня лично он все время глаз режет. |
|
06.12.2013, 07:04 | #4 |
NavAx
|
А тебе не приходила в голову мысль о том, что марка машины и компетентность коррелируют слабо? Возможен ли такой вариант, что когда-то система ругнулась, что не хватает tts-ов, вот он их и вставил? Получил бонус, может даже повышение.
Может ли так случиться, что некий разработчик любой ценой будет отстаивать принятные решения исключительно для того, чтобы не потерять лицо и мерседес? И возможна ли такая ситуация, что ты роешь не код, а под своего пакистанского коллегу? Так вот, если это ваш случай, не думай что он этого не видит. Может в коде наши пакистанские коллеги не всегда разбираются, зато уж по части иерархии и карьеризма им можно большую фору дать.
__________________
Isn't it nice when things just work? |
|
|
За это сообщение автора поблагодарили: gl00mie (1). |
06.12.2013, 08:23 | #5 |
Участник
|
Цитата:
Ну и как говориться - не можешь решить проблему, измени свое отношение к ней". А это проблема не пакистанца с мерседесом, а многих "программистов", там еще и не такое встретить можно. |
|
06.12.2013, 08:28 | #6 |
Участник
|
Нет. Это равносильно тому, что бы вообще не писать ttsbegin/ttscommit а использовать skipTTSCheck(true).
Если критична атомарность операции обновления всех записей запроса то транзакцию обязательно нужно открывать до цикла, а если не критична, то можно сделать например вот так X++: while select forUpdate myTable { ttsBegin; // -->> myTable.reread(); // перевыбираем запись // <<-- myTable.MyField = 'something'; myTable.update(); ttsCommit; } |
|
|
За это сообщение автора поблагодарили: ax_mct (2). |
06.12.2013, 11:21 | #7 |
Участник
|
Цитата:
Сообщение от ax_mct
Есть неплохой разбор в статье
https://community.dynamics.com/ax/b/...c-locking.aspx What normally I use in the most cases from version AX 4.0 and the author did not mention about that way. while select myTable { ttsBegin; myTable.selectForUpdate(true); myTable.MyField = 'something'; myTable.update(); ttsCommit; } |
|
|
За это сообщение автора поблагодарили: ax_mct (2). |
06.12.2013, 15:47 | #8 |
Banned
|
Цитата:
Сообщение от macklakov
А тебе не приходила в голову мысль о том, что марка машины и компетентность коррелируют слабо? Возможен ли такой вариант, что когда-то система ругнулась, что не хватает tts-ов, вот он их и вставил? Получил бонус, может даже повышение.
Может ли так случиться, что некий разработчик любой ценой будет отстаивать принятные решения исключительно для того, чтобы не потерять лицо и мерседес? И возможна ли такая ситуация, что ты роешь не код, а под своего пакистанского коллегу? Так вот, если это ваш случай, не думай что он этого не видит. Может в коде наши пакистанские коллеги не всегда разбираются, зато уж по части иерархии и карьеризма им можно большую фору дать. Там еще и другая "фича" - этот метод (перебирающий записи в SalesTable и SalesLine и обновляющий их) находится внутри try catch retry. То есть при update conflict на одной записи вся таблица будет перебрана и обновлена заново Да бог с этим. Слава богу я контрактник и не в постоянном коллективе поэтому вопросы иерархии и карьеризма для меня упрощаются. |
|
06.12.2013, 15:52 | #9 |
Banned
|
Цитата:
Сообщение от LeonDerCom
Вам не кажется, что это не крик души программиста о "неправильном" коде, ну а несколько иное?
Ну и как говориться - не можешь решить проблему, измени свое отношение к ней". А это проблема не пакистанца с мерседесом, а многих "программистов", там еще и не такое встретить можно. |
|
06.12.2013, 15:58 | #10 |
Banned
|
Цитата:
Есть еще поддержка пессимистического режима. То есть по идее такой код (в первом посту который с заГраничным select for update) не пройдет сертификации в MS и не должен использоваться в вертикальных и общих решениях. Только на конкретном клиенте. Так как при отключении OCC работать не будет. |
|
06.12.2013, 19:35 | #11 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: ax_mct (2). |
06.12.2013, 20:21 | #12 |
Banned
|
X++: static void Job21(Args _args) { InventTable inventTable; ; inventTable = InventTable::find("какая-нибудь", true); ttsbegin; //inventTable = InventTable::findRecId(inventTable.recId, true); //inventTable.reread(); inventTable.update(); ttscommit; } Хитрости с reread и skipTTSCheck да помогут поставить кривой стол ровно. Но вот сдается мне что это совсем не Best Practices Хотя все зависит от того насколько обновляемые поля относятся к бизнес логике то есть если сугубо техническое и скрытое поле это одно а доступное для всех и связанное с другими это другое. В "стандартном" программировании будет сидеть в углу администратор базы данных и говорить что так нельзя и не надо. А когда каждый AX программист сам себе архитектор и программист базы данных без контроля то мне кажется это неверно. Хотя это дает мне работу по разгребанию. Главное чтобы в результате такой гибкости AX (переходящей к ненадежности) клиенты не убежали на SAP Впрочем я верю в маркетинг MS. Даже думаю а не сделать ли мне облачную AX для подсчета овец |
|
|
|