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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 05.02.2009, 18:35   #1  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Итак, по-порядку:
Про запрос - спасибо. Это, думаю, достаточное подтверждение того, что второй будет быстрее.
Забыл сразу написать, из головы выпало...

Ещё одним доводом в пользу скорости второго варианта может быть то, что в исходном варианте приходится ещё бежать по курсору и перегонять данные на клиента. Во втором - передаётся только одна, уже посчитанная, сумма.
Так что даже если на сервере запросы выполнятся примерно за сопоставимое время - передача данных по сети может эту разницу увеличить (прямо пропорционально размеру заказа).
(О том насколько большим может быть это влияние я как раз недавно вскользь упоминал вот тут)
__________________
Zhirenkov Vitaly
Старый 05.02.2009, 19:26   #2  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Поехали дальше....

2 на мой взгляд бага на 4-ке сп2 с нашей локализацией (восточная европа), слои GLS & GLP.
(На 2009 локализации пока не видел, так что не знаю как там... Может ещё не поздно предупредить )

Таблицы PurchLine & SalesLine.

Для начала метод PurchLine.delete()
(та же картина, только вид сбоку, наблюдается и в SalesLine.insert() и в SalesLine.update() - но там касается только братьев-поляков )
X++:
public void  delete(boolean _showInfoDelReserv = true, boolean deletePBA = true)
{
    PurchLineType purchLineType;
    ;

    purchLineType = this.type();
    purchLineType.delete(_showInfoDelReserv, deletePBA);

    TaxWorkRegulation::deleteRegulation_W(this);
}
В purchLineType.delete() одна транзакция, в TaxWorkRegulation::deleteRegulation_W() - другая. А как же понятие атомарности действия? Одна транзакция прошла, вторая свалилась, ну и ладно? Нехорошо, как-то...

Теперь перейдём к методу SalesLine.delete():
X++:
void delete(Common childBuffer = null, boolean deletePBA = true)
{
    SalesLineType  salesLineType;
    ;

    ttsbegin;

    if (this.AssetId_RU && this.SalesStatus != SalesStatus::Invoiced && ! this.creditNoteLine())
    {
        RAssetTable::updateStatus(this.AssetId_RU, RAssetStatus::Open);
        RAssetTable::updateCustInfo(this.AssetId_RU, '', '');
    }

    salesLineType = this.type();
    salesLineType.delete(childBuffer, deletePBA);

    TaxWorkRegulation::deleteRegulation_W(this);

    ttscommit;
}
Оппачки, тут уже внесли всё в одну транзакцию! Казалось бы, круто, молодцы! НО! Что мы видим в salesLineType.delete()?
Видим внутреннюю транзакцию и перехват ошибок типа Deadlock, UpdateConflict и т.п.
И что происходит из-за появления "внешней" транзакции на SalesLine.delete()?
Правильно, весь эти тщательно пИсаный старшими товарищами код по перехвату ошибок дружно встаёт и уходит сами знаете куда...
Нехорошо, как-то...

Я всё-таки в подобных случаях предпочитаю вносить все свои доработки в единую транзакцию в класс Sales/PurchSalesLine. И, на мой взгляд, так должны были поступить и "локализаторы"...
Или я пропустил какую-то глубокую мысль, которую всё это преследовало?
__________________
Zhirenkov Vitaly
Старый 05.02.2009, 22:02   #3  
Jabberwocky is offline
Jabberwocky
Microsoft Dynamics
Аватар для Jabberwocky
Сотрудники Microsoft Dynamics
 
274 / 307 (11) ++++++
Регистрация: 02.09.2005
Адрес: Москва
Уважаемый ZVV, Вы правы лишь отчасти, и то - с точностью до наоборот. Попробуйте в методе PurchLine.delete() заменить
X++:
TaxWorkRegulation::deleteRegulation_W(this);
на что-нибудь вроде:
X++:
ttsbegin;
throw error('');
ttscommit;
Уверяю Вас, удалить строку закупки Вам после этого не удастся, т.к. при удалении строки из формы неявно (implicit) инициируется транзакция, и возникновение исключения внутри неё или в любой из вложенных транзакций откатывает её (и все вложенные транзакции) полностью.

Отсюда Ваш вывод относительно кода в SalesLine.delete(); также неверен, - здесь как раз транзакционные скобки являются лишними, но их присутствие не так уж критично.
__________________
You should use Bing before asking dumb questions.

Последний раз редактировалось Jabberwocky; 05.02.2009 в 22:10.
За это сообщение автора поблагодарили: ZVV (1).
Старый 05.02.2009, 23:58   #4  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Вы чертовски правы, Jabberwocky. Действительно, всё наоборот. Слона то я (неявного) и не приметил. Спасибо!

Даже если вызовы идут и не из формы, а в коде, то там всё равно практически всегда будет присутствовать явная транзакция извне... Разве что вставку можно без транзакции сделать, и тогда всё-таки SalesLine.insert() пройдёт в двух транзакциях. Но это не сильно типичная ситуация, имхо.

Тогда сформулирую обратный вопрос: а зачем в методах Sales/PurchSalesLine.insert/update/delete() организованы эти масштабные try-catch блоки? Ведь получается они никогда не работают, или всё таки работают, но тогда что-то не понимаю когда?
__________________
Zhirenkov Vitaly
Старый 16.02.2009, 19:35   #5  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
Сообщение от ZVV Посмотреть сообщение
Тогда сформулирую обратный вопрос: а зачем в методах Sales/PurchSalesLine.insert/update/delete() организованы эти масштабные try-catch блоки? Ведь получается они никогда не работают, или всё таки работают, но тогда что-то не понимаю когда?
Работают в случае Exception::UpdateConflict, как минимум:
TTS и try..catch
Старый 17.02.2009, 11:06   #6  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Цитата:
Сообщение от alex55 Посмотреть сообщение
Работают в случае Exception::UpdateConflict, как минимум:
TTS и try..catch
Ну да, перехватит, конечно...
И отправит дальше!
Потому что appl.ttsLevel() <> 0...
__________________
Zhirenkov Vitaly
Старый 17.02.2009, 17:27   #7  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5813 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от ZVV Посмотреть сообщение
X++:
if (! this.validate())
    throw error("");
считаю, что
X++:
throw Exception::Error;
как-то посимпатичнее и пишу в таких случаях именно так.
Это зачастую просто некорректно с точки зрения информативности выводимых ошибок. Точнее, в некорректности ошибок будет виновата сама Аксапта, но пользователю от этого не легче.
Цитата:
Сообщение от glibs Посмотреть сообщение
А с другой стороны почему бы не написать лишний раз, что не получилось там что-то сделать.
Мне кажется, в таких ситуациях просто необходимо писать еще какое-то сообщение - и вот по какой причине:
  • у Аксапты есть замечательная, пусть и несско глючная, возможность указывать префиксы для выводимых сообщений, что позволяет создавать информативные сообщения и в то же время не тянуть всю необходимую для них информацию через весь стек вызываемых методов (например, «обработка заказа такого-то/строка ндцатая, номенклатура такая-то/проверка блокировок/склад такой-то/заблокировано по складу»);
  • построение дерева сообщений infolog'а (я так понимаю, \Classes\Info\viewBuild) криво работает с префиксами, если сообщение лишь одно; т.е. в этом случае префикс почему-то не используется, будто он важен, лишь когда сообщений несколько.
В результате, если в данном примере метод validate() вызывает кучу вложенных методов, и на разных уровнях стэка вызова устанавливаются префиксы для возможных сообщений, а затем выводится одно сообщение об ошибке (скажем, из-за того, что номенклатура такая-то заблокирована по складу такому-то), то в приведенном выше примере в случае простого выброса Exception::Error в инфолог выведется лишь «заблокировано по складу» без какой-либо детализации, закладываемой в префиксы на каждом уровне стека вызова. Дополнительное же сообщение, наподобие "модификации были отменены", поспособствует тому, что инфолог построит нормальное дерево сообщений со всеми префиксами.
За это сообщение автора поблагодарили: alex55 (1).
Старый 12.02.2009, 17:35   #8  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Небольшой "бажок" на 4.0сп2 (в 2009 этот функционал регистрации отгрузочных накладных переделали, и там этой таблицы уже нет). Но может кому пригодится...

Таблица InventPickingListJournalLine, метод splitByInventTrans

В последнем delete_from явно забыли поле поменять после "копи-пасте"
Вместо
X++:
                inventPickingListJournalLine.InventTransChildType   == this.InventTransChildType    &&
                inventPickingListJournalLine.InventTransChildType   == this.InventTransChildType    &&
должно неверное таки быть:
X++:
                inventPickingListJournalLine.InventTransChildType   == this.InventTransChildType    &&
                inventPickingListJournalLine.InventTransChildRefId   == this.InventTransChildRefId   && // ZVV, Bug fix
__________________
Zhirenkov Vitaly
Старый 17.02.2009, 16:05   #9  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
-> Разноска отборочной из отгрузок
dax 2009 sp 1

Создание отборочной из отгрузки...
Имеет место 2 следующих (на мой сугубо личный взгляд - слабо предсказуемых) эффекта (или бага, как кому нравится), оба связаны с ситуацией, когда строка заказа на продажу коплектуется несколькими отгрузками.
Т.е., например, в строке заказа количество 5, из них 2 и 3 обработаны разными отгрузочными и соответсвенно пошли в строки разных отгрузок.

1. При попытке обработать отборочную по двум данным отгрузкам сразу (выделить 2-е на форме отгрузок) обработается только одна из строк отгрузки.
Причина:
класс SalesTotals_ParmTrans
X++:
protected void initRecordSortedListLine()
{
    ;
    recordSortedListLine = new RecordSortedList(tablenum(SalesParmLine));

    recordSortedListLine.sortOrder(fieldnum(SalesParmLine, TableRefId),
                                   fieldnum(SalesParmLine, OrigSalesId),
                                   fieldnum(SalesParmLine, LineNum),
                                   fieldnum(SalesParmLine, SalesLineRecId));
}
Как не сложно догадаться, данный "сортОрдер" является одинаковым для обоих строчек,
в следствие чего при заполнении в этот лист списка строчек, последняя (с кол-вом 3) перезатрёт предыдущую (с кол-вом 2).
Это в классе TradeTotals, метод calc()
X++:
recordSortedListLine.ins(orderLine);
В результате обработается только кол-во из "последней" строки...

Возможные варианты - либо в этом же методе проверять наличие подобной строки в recordSortedListLine и, если есть - суммировать кол-ва (правда в этом случае придётся отдельно проработать вопрос оставшегося кол-ва по строке).
Пробовал на 2009 реализовывать - работает.
Как альтернатива (такое у нас реализовывалось на 3-ке) - переделывать запрос на более ранннем этапе -
в SalesFormLetter_PackingSlip.chooseLinesFromWMSShipmentSet(). По сравнению с той же 3-кой тут кой-чего уже переделали, некоторые баги поправили, но как-то не до конца.
Тут можно переписать, вместо последнего цикла сделать Query по всем имеющимся отгрузкам и изначально просуммировать все нужные кол-ва в одну строку ещё на форме разноска.
Как третий вариант (сам не пробовал, может он и нереализуем) - как-то изменить recordSortedListLine.sortOrder для данного случая.

2. Второй баг более тяжело объяснить... Счас будет много местами бессвязных слов, но кто с этим кодом\функционалом разбирался - надеюсь поймёт.
Теперь разносим только одну отгрузу из двух описанных выше.

Есть метод SalesFormLetter_PackingSlip.resetProformaUponPhysicalUpdatable(), который определяет будет ли реально производится разноска - он работает на основе полей маршрута из WMSOrderTrans и InventTrans.
Т.е. можно разносить, только если ещё остались проводки неразнесённые с таким маршрутом. (иначе будет proforma)
Появляются следующие проблемы:

а) при реальной разноске отборочной эти маршруты никак не учитываются и разнося отборочную по одной отгрузке мы можем разнести проводки по маршруту другой отгрузки.
В итоге чтобы разнести отборочную по второй придётся ещё раз разносить её по первой отгрузке. (извините за каламбур, я предупреждал )
А разнося первую мы как бы разнесли вторую.
И вообще когда таких отгрузок много, можно получить много всяких непредсказуемых эффектов с доступностю птички "разноска" при разноске отборочной по различным отгрузкам.

б) даже если передположить, что проводки будут разноситься по нужным маршрутам, есть ещё проблема, с количеством.
Возвращаемся к примеру с разбитой на 2 отгрузки строкой. 2 и 3.
Предположим мы разносим отгрузку с кол-вом 3, уменьшаем там кол-во до 2-х и разносим.
Остаётся в одной отгрузке 2, в другой - 1. Теперь пытаемся опять разнести ту же отгрузку.
Благодаря методу SalesFormLetter_PackingSlip.createParmLineFromWMSOrderTrans() который проверяет только общее кол-во скомплектованных по строке заказа (без учёта отгрузок и маршрутов), нам опять предложат разнести кол-во 3, и разноска эта пройдёт без проблем, в результате чего разнесётся сразу всё оставшееся кол-во (3).
Т.е. разнося одну отгрузку - мы разнесли обе.
Не знаю, может так, конечно, и задумывалось, но со стороны выглядит как-то уж очень кривенько...

б) решается, вероятно, довольно просто, если SalesFormLetter_PackingSlip.createParmLineFromWMSOrderTrans() проверять не общее кол-во скомплектованных проводок по строке заказа,
X++:
    InventQty       qtyPicked       = _salesLine.pickedInTotalInventUnit();
а только по нужному маршруту.
с а) - кажется сложнее, тут надо параметр какой-то в разноску добавлять, что-ли. Возможно из-за лишнего геморроя на этот момент и решили забить. Не такой уж и частый случай, типа...

PS sorry за многабукаф, короче не получилось...
__________________
Zhirenkov Vitaly
Теги
bug report, баг, ошибка, dynamics

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Баги WebTab в DAX4 (более 1-ого на форме) alex55 DAX: Программирование 4 11.07.2008 16:28
Сергей Герасимов: Бизнес-приложения – основа стратегии корпорации Майкрософт Blog bot DAX Blogs 5 27.09.2007 02:00
Сергей Герасимов: О новостных группах и других общедоступных ресурсах Майкрософт Blog bot DAX Blogs 0 09.02.2007 22:52
Сергей Герасимов: Майкрософт ежемесячно публикует список исправленных ошибок Blog bot DAX Blogs 1 16.01.2007 11:52
Счет на оплату по заказу. Баги. Косых Артём DAX: Программирование 2 23.06.2006 11:32

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

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

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