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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 19.05.2017, 10:59   #1  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
? InventSumDelta и InventSum - как проще писать запросы и переносить старый код.
Добрый день.
Собственно тема в заголовке.

В руки попал большой проект на 2012-й аксапте. Код изначально похоже был написан еще в ax3.0. Во многих местах для получения остатков запросы идут к InventSum без учета InventSumDelta. В связи с этим вопрос. Если возникнет необходимость, как можно по-быстрому перевести код для учета InventsumDelta без какого либо серьезного переписывания.

Первая идея - сделать хитрую вьюху (InventSumView) cо структурой полей аналогичной InventSum, которая делает union InventSum и InventSumDelta (но из InventSumDelta нужно взять актуальные для нас строки, фильтруя их по TTSid). А дальше в коде по мере необходимости заменять запрос к InventSum на InventSumView. Тем самым соблюдается требование на минимальные переделки в коде. Можно в коде в разделе объявления переменных заменять одну строку
X++:
Inventsum   inventsum;
на
X++:
InventsumView   inventsum;
и дело в шляпе.

Средствами X++ такую вьюху создать затруднительно. По крайней мере у меня пока нет идей, кроме как подменять ее определение в SQL.

Как замена создал Union-Query GRD_InventSumAllQuery (данные во вложении).
Там описанная идея реализована. Фильтрация по InventsumDelta.TTSid работает.
На SQL уходит примерно такой запрос
X++:
SELECT T1.ARRIVED,T1.AVAILORDERED,T1.AVAILPHYSICAL,T1.DEDUCTED,T1.INVENTDIMID,T1.ITEMID,T1.LASTUPDDATEEXPECTED,T1.LASTUPDDATEPHYSICAL,T1.ONORDER,T1.ORDERED,T1.PHYSICALINVENT,T1.PHYSICALVALUE,T1.PHYSICALVALUESECCUR_RU,T1.PICKED,T1.POSTEDQTY,T1.POSTEDVALUE,T1.POSTEDVALUESECCUR_RU,T1.QUOTATIONISSUE,T1.QUOTATIONRECEIPT,T1.RECEIVED,T1.REGISTERED,T1.RESERVORDERED,T1.RESERVPHYSICAL,T1.RECID,1
FROM INVENTSUM T1
WHERE ((PARTITION=5637144576)
AND (DATAAREAID=N'GRD')) UNION ALL
SELECT T1.ARRIVED,T1.AVAILORDERED,T1.AVAILPHYSICAL,T1.DEDUCTED,T1.INVENTDIMID,T1.ITEMID,T1.LASTUPDDATEEXPECTED,T1.LASTUPDDATEPHYSICAL,T1.ONORDER,T1.ORDERED,T1.PHYSICALINVENT,T1.PHYSICALVALUE,T1.PHYSICALVALUESECCUR_RU,T1.PICKED,T1.POSTEDQTY,T1.POSTEDVALUE,T1.POSTEDVALUESECCUR_RU,T1.QUOTATIONISSUE,T1.QUOTATIONRECEIPT,T1.RECEIVED,T1.REGISTERED,T1.RESERVORDERED,T1.RESERVPHYSICAL,T1.RECID,2
FROM INVENTSUMDELTA T1
WHERE (((PARTITION=5637144576)
AND (DATAAREAID=N'GRD'))
AND ((ISAGGREGATED=0)
AND (TTSID=5637758929)))
ORDER BY 6
Жаль что нельзя обращаться с Query как с вьюхой. Если бы такой было можно то проблема была бы решена, а так похоже придется извращаться с подменой текста вьюхи в SQL.

Может есть идея как еще можно сделать ?

P.S.
Ax2012 R3 CU9
P.P.S.
В этой теме
Остатки по номенклатуре в разрезе складов внутри транзакции
было обсуждение похожей проблемы
Предложили хорошие варианты решения, но здесь они не подходят так как придется сильно код переписывать.

Последний раз редактировалось Logger; 19.05.2017 в 11:05.
Старый 19.05.2017, 11:19   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Logger Посмотреть сообщение
как можно по-быстрому перевести код для учета InventsumDelta без какого либо серьезного переписывания.
Хм... мне кажется, что стоит уточнить формулировку.

InventsumDelta "живет" только в рамках транзакции.
при завершении транзакции все дельта переносятся в inventSum

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

в остальных случаях inventSum вполне достаточно.

тебе точно дельта нужна?
__________________
полезное на axForum, github, vk, coub.
Старый 19.05.2017, 11:24   #3  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Это я понимаю. Вопрос задан именно для тех случаев когда нужна дельта. Я понимаю что это не всегда надо.

Т.е. вопрос в том, что если потребовалось учесть дельту, то как это сделать максимально простым способом без сильных переписываний и не мучаясь с объединением результатов двух запросов.
Старый 19.05.2017, 11:28   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Плюс, если бы можно было создать такую вьюху или если бы с квериком из примера можно было бы обращаться как с вьюхой или табличным мапом, то можно было бы всегда ее в коде использовать.

Так было бы удобнее. Потому что, написал, например, программист какой-нибудь класс, который в процессе работы делает запрос к Inventsum и на основе остатков что-то делает. А затем этот класс захотели использовать в рамках другого более сложного алгоритма в одной транзакции. И тут лезут проблемы. Оказывается что остатки в InventSum неактуальные и все такое. Т.е. код использующий InventSum - не совсем переносимый. Его в другом месте просто так не заюзаешь.

А всего-то надо, чтобы ядро позволяло использовать Query как табличный map или View и дело в в шляпе. (Просто создать View на основе Query не прокатывает. Query позволяет динамически фильтры формировать, а View в момент создания их фиксирует)

Последний раз редактировалось Logger; 19.05.2017 в 11:38.
Старый 19.05.2017, 11:37   #5  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
мне кажется, что обсуждение вопроса можно и должно разложить на случаи:
1. сделать быстро
2. сделать хорошо
2.1. сделать хорошо select
2.2. сделать хорошо query

для начала хотелось бы убедиться что способ "сделать быстро" не подходит по тем или иным причинам.

итак, "сделать быстро":
есть группа методов InventSum.addInventSumDelta

эти методы работают следующим образом:
  • стандартный алгоритм где-то и как-то получает inventSum обычным образом
  • программист добавляет/вызывает код, который рассчитывает/находит inventSumDelta для данного inventSum (методы InventSumDelta.findSumDelta, newQuery, summarizeDelta* и т.п.)
  • программист вызывает код, который добавляет найденную дельту к найденной сумме - InventSum.addInventSumDelta
  • Profit

да, это далеко не оптимальный с точки зрения производительности способ.
но легко программируется и легко читается при поддержке.

мне кажется, что этот способ стоит использовать даже в случае 2.1.

для 2.2. лучше использовать стандартные методы NewQuery, queryAddSumFields и подобные. главное, не вклиниваться в исходный код, а сделать... хм... extension.
__________________
полезное на axForum, github, vk, coub.
Старый 19.05.2017, 11:39   #6  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,890 / 5647 (194) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Можно посмотреть на sysComputedColumn и примеры его использования.
По большому счету - весь этот механизм генерирует текст с определением вычислимого поля для view. Более того - есть подозрение что при некотором упорстве туда тупо можно засунуть SQL, который эту колонку будет рассчитывать для данного itemId и inventDim. То есть - написать хранимку в сиквеле, а потом в DAX2012 определить view состоящий из inventSum и вычислимого поля. А в самом определении поля засунуть вызов хранимки с текущим значением inventSum.itemId и inventSum.inventDimId. Конечно хранимка будет не очень быстро работать и на большой выборке запрос по подобному view будет работать долго, но для конкретных небольших выборок оно вполне даже может прилично отрабатывать... Можно кстати определить вычислимое поле как inventSum.postedQty+unconfirmedPostedQty(inventSum.itemId, inventSum.inventDimId).
Есть правда проблема того как обрабатывать ситуацию с текущей сессией, по которой надо собирать неподтвержденные операции. Я бы попытался сделать картезианское произведение SysClientSessions и InventSum, при этом значение sessionId передавал бы в хранимую процедуру. Также SessionId надо будет вывести как дополнительное поле во view, а в любых запросах писать что-то типа:
Select sum(postedQty)
from mySuperView
where mySuperView.sessionId==sessionId() && mysuperView.itemid==itemId
В общем - в зависимости от мощности вашего сервера оно может сработать, а может и не сработать
За это сообщение автора поблагодарили: Logger (3).
Старый 19.05.2017, 11:41   #7  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от fed Посмотреть сообщение
Можно посмотреть на sysComputedColumn и примеры его использования.
это конечно да... но количество модификаций, которое нужно сделать и протестировать будет очень большим.
мне кажется, что для грязных данных. это какой-то перебор.
__________________
полезное на axForum, github, vk, coub.
Старый 19.05.2017, 12:06   #8  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Основная проблема как мне кажется - научить вьюху отбирать из InventSumDelta записи с нужным TTSid - актуальным для текущей сессии.

Можно в служебную табличку (XXServiceTable ) в начале транзакции (в методе application.ttsNotifyPostBegin писать соответствие ttsId и @@SPID - до конца транзакции ни ttsId ни @@SPID не поменяется. А за пределами транзакции для уже поюзанного номера ttsId выборка из InventSumDelta всегда пустая)
Ну а затем во вьюхе добавить условие - фильтровать InventSumDelta.TTsId по значению прописанного в вспомогательной табличке. Его легко достать через подзапрос
X++:
select ttsId from XXServiceTable where sid = @@SPID
.

По идее это все не должно утяжелить запрос. Данные в InvnetSumDelta игрушечные по сравнению с Inventsum. Она практически всегда пустая.

Последний раз редактировалось Logger; 19.05.2017 в 12:09.
Старый 19.05.2017, 12:17   #9  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,890 / 5647 (194) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Можно еще context_info использовать. Указывать контекстную информацию в postTtsBegin() и очишать в preTTSCommit()
Старый 19.05.2017, 12:44   #10  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Да точно.
Я тоже сперва про нее подумал, но потом решил отказаться. У нас в реестре включен флажок (Мониторинг работы), по которому ядро в эту переменную пишет разную служебную инфу. Боюсь пересекутся.

Последний раз редактировалось Logger; 19.05.2017 в 12:46.
Старый 19.05.2017, 13:16   #11  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Пример с 1-го раза не вложился.
Вложения
Тип файла: zip InventsumDeltaExample.zip (9.2 Кб, 127 просмотров)
Старый 22.05.2017, 22:26   #12  
Ярослав Щекин is offline
Ярослав Щекин
Участник
 
78 / 174 (6) ++++++
Регистрация: 16.03.2009
Цитата:
Сообщение от Logger Посмотреть сообщение
Основная проблема как мне кажется - научить вьюху отбирать из InventSumDelta записи с нужным TTSid - актуальным для текущей сессии.
Хмм... я правильно помню, что вне транзакции InventSumDelta всегда пустая, т.е. она всегда очищается по завершениии транзакции?
Далее, для запросов (без forupdate) в Ax2012 всё ещё используется Read Committed Snapshot Isolation?
Если всё это так, то "чужие" записи в ней просто невозможно увидеть, т.е. условие по ttsId, казалось бы, просто не нужно (оно лишь оптимизирует выборку)...
За это сообщение автора поблагодарили: Logger (3).
Старый 23.05.2017, 09:20   #13  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,860 / 3109 (111) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
На первый взгляд это так, но как-то это ненадежно. Высок риск получить блокировку. Т.е. для поиграться - подойдет, а на продуктиве как-то стремно писать код который закладывается на такие вещи.
Теги
ax2012, inventsum, inventsumdelta

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Множественные запросы по DataArea и VirtualDataAreaList Dreadlock DAX: Программирование 11 24.07.2012 11:43
Channel9: Peter Villadsen and Gustavo Plancarte: X++ to MSIL Blog bot DAX Blogs 30 24.08.2010 17:11
Запросы / Итоги для ЗПР Prophetic DAX: Программирование 5 02.08.2010 15:13
Странный код в InventSum.update() и deadlocks Shannon DAX: Программирование 4 12.04.2010 15:36
Запросы к связанным таблицам Rect DAX: Программирование 14 05.06.2007 10:16
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 06:29.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.