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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 06.12.2013, 00:10   #1  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
? 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  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Есть неплохой разбор в статье
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  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Один мой товарищ мне написал "Компилятор распознаёт это правильно, почему бы и нет".

Но компилятор и даже BP много чего пропускает.
Был бы он умный не было бы runtime errors.

И скажем сертифицирование такой код не пройдет и более или менее нормален на конкретном End User. Так как работает только при оптимистической конкуренции. Что же это за код который сломается при изменении настроек на таблице или в приложении? Я лично не могу такой код писать.

И есть у меня подозрения что SQL server не любит такое просто его никто не слышит.

Была бы моя власть я бы не пропускал такой код. Те кто программировал до AX 4.0 вряд ли так программируют. У меня лично он все время глаз режет.
Старый 06.12.2013, 07:04   #4  
macklakov is offline
macklakov
NavAx
Аватар для macklakov
 
2,245 / 980 (37) +++++++
Регистрация: 03.04.2002
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Вот мои комментарии к статье своим собратьям на мерседесах.
А тебе не приходила в голову мысль о том, что марка машины и компетентность коррелируют слабо? Возможен ли такой вариант, что когда-то система ругнулась, что не хватает tts-ов, вот он их и вставил? Получил бонус, может даже повышение.
Может ли так случиться, что некий разработчик любой ценой будет отстаивать принятные решения исключительно для того, чтобы не потерять лицо и мерседес? И возможна ли такая ситуация, что ты роешь не код, а под своего пакистанского коллегу?
Так вот, если это ваш случай, не думай что он этого не видит. Может в коде наши пакистанские коллеги не всегда разбираются, зато уж по части иерархии и карьеризма им можно большую фору дать.
__________________
Isn't it nice when things just work?
За это сообщение автора поблагодарили: gl00mie (1).
Старый 06.12.2013, 08:23   #5  
LeonDerCom is offline
LeonDerCom
Участник
 
45 / 20 (1) +++
Регистрация: 08.10.2012
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Я очень часто вижу такой стиль. Лично мне он как то неприятен.
Потратил сегодня вечер анализируя это так как пакистанец (неплохой программист с Mерседесом) написал именно так. [/XPP]
Вам не кажется, что это не крик души программиста о "неправильном" коде, ну а несколько иное?
Ну и как говориться - не можешь решить проблему, измени свое отношение к ней". А это проблема не пакистанца с мерседесом, а многих "программистов", там еще и не такое встретить можно.
Старый 06.12.2013, 08:28   #6  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Вы так программируете?
Нет. Это равносильно тому, что бы вообще не писать ttsbegin/ttscommit а использовать skipTTSCheck(true).

Если критична атомарность операции обновления всех записей запроса то транзакцию обязательно нужно открывать до цикла, а если не критична, то можно сделать например вот так

X++:
while select forUpdate myTable
{
    ttsBegin;
// -->>
    myTable.reread(); // перевыбираем запись 
// <<-- 
    myTable.MyField = 'something';
    myTable.update();
    ttsCommit;
}
Common.reread() - альтернатива для findRecId?
За это сообщение автора поблагодарили: ax_mct (2).
Старый 06.12.2013, 11:21   #7  
skuull is offline
skuull
Участник
Most Valuable Professional
Лучший по профессии 2014
 
700 / 752 (27) +++++++
Регистрация: 08.03.2013
Адрес: ХЗ
Цитата:
Сообщение от 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;
}
Попробуйте в 2012 сделать так с любой дочерней таблицей - получите рантайм
За это сообщение автора поблагодарили: ax_mct (2).
Старый 06.12.2013, 15:47   #8  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от macklakov Посмотреть сообщение
А тебе не приходила в голову мысль о том, что марка машины и компетентность коррелируют слабо? Возможен ли такой вариант, что когда-то система ругнулась, что не хватает tts-ов, вот он их и вставил? Получил бонус, может даже повышение.
Может ли так случиться, что некий разработчик любой ценой будет отстаивать принятные решения исключительно для того, чтобы не потерять лицо и мерседес? И возможна ли такая ситуация, что ты роешь не код, а под своего пакистанского коллегу?
Так вот, если это ваш случай, не думай что он этого не видит. Может в коде наши пакистанские коллеги не всегда разбираются, зато уж по части иерархии и карьеризма им можно большую фору дать.
Он неплохой по местным меркам программист и адекватный человек. Как выяснилось полностью скопировал класс сделанный очень известным интегратором и просто заменил поле. И он согласился с моими доводами но осадок у него остался, так как я играю не по их правилам общения в принципе.

Там еще и другая "фича" - этот метод (перебирающий записи в SalesTable и SalesLine и обновляющий их) находится внутри try catch retry. То есть при update conflict на одной записи вся таблица будет перебрана и обновлена заново
Да бог с этим.

Слава богу я контрактник и не в постоянном коллективе поэтому вопросы иерархии и карьеризма для меня упрощаются.
Старый 06.12.2013, 15:52   #9  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от LeonDerCom Посмотреть сообщение
Вам не кажется, что это не крик души программиста о "неправильном" коде, ну а несколько иное?
Ну и как говориться - не можешь решить проблему, измени свое отношение к ней". А это проблема не пакистанца с мерседесом, а многих "программистов", там еще и не такое встретить можно.
Да согласен просто приступ перфекционизма на фоне текущих просьб пофиксить данные на живом приложении. В целом я конечно неправ.
Старый 06.12.2013, 15:58   #10  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Нет. Это равносильно тому, что бы вообще не писать ttsbegin/ttscommit а использовать skipTTSCheck(true).

Если критична атомарность операции обновления всех записей запроса то транзакцию обязательно нужно открывать до цикла, а если не критична, то можно сделать например вот так
Спасибо. А то я начал думать что я просто псих придумывающий проблемы.

Есть еще поддержка пессимистического режима. То есть по идее такой код (в первом посту который с заГраничным select for update) не пройдет сертификации в MS и не должен использоваться в вертикальных и общих решениях. Только на конкретном клиенте. Так как при отключении OCC работать не будет.
Старый 06.12.2013, 19:35   #11  
Player1 is offline
Player1
Участник
Самостоятельные клиенты AX
 
306 / 137 (5) +++++
Регистрация: 21.04.2008
Старый топик "Как правильно обновить"
За это сообщение автора поблагодарили: ax_mct (2).
Старый 06.12.2013, 20:21   #12  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
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 для подсчета овец
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Ответ: По поводу while select forUpdate AndyD DAX: Программирование 2 19.07.2012 18:32
dynamics-ax-dev: CLR Errors & ttsbegin/ttscommit Blocks Blog bot DAX Blogs 0 02.11.2010 18:05
Целесообразность отмены пересчетов перед закрытием склада vc DAX: Функционал 2 18.04.2010 16:54
FORUPDATE не может использоваться для представления - Предупреждение от АОСа /Antony/ DAX: Администрирование 4 09.11.2009 13:01
ttsbegin ttscommit and changecompany() Volodymyr DAX: Программирование 9 29.08.2008 15:36

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

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

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