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 19.05.2017, 10:59   #1  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Join Date: 12.10.2004
Location: Москва
Blog Entries: 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.
В этой теме
Остатки по номенклатуре в разрезе складов внутри транзакции
было обсуждение похожей проблемы
Предложили хорошие варианты решения, но здесь они не подходят так как придется сильно код переписывать.

Last edited by Logger; 19.05.2017 at 11:05.
Old 19.05.2017, 11:19   #2  
mazzy is offline
mazzy
Участник
mazzy's Avatar
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Join Date: 29.11.2001
Location: Москва
Blog Entries: 10
Quote:
Originally Posted by Logger View Post
как можно по-быстрому перевести код для учета InventsumDelta без какого либо серьезного переписывания.
Хм... мне кажется, что стоит уточнить формулировку.

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

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

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

тебе точно дельта нужна?
__________________
полезное на axForum, github, vk, coub.
Old 19.05.2017, 11:24   #3  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Join Date: 12.10.2004
Location: Москва
Blog Entries: 2
Это я понимаю. Вопрос задан именно для тех случаев когда нужна дельта. Я понимаю что это не всегда надо.

Т.е. вопрос в том, что если потребовалось учесть дельту, то как это сделать максимально простым способом без сильных переписываний и не мучаясь с объединением результатов двух запросов.
Old 19.05.2017, 11:28   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Join Date: 12.10.2004
Location: Москва
Blog Entries: 2
Плюс, если бы можно было создать такую вьюху или если бы с квериком из примера можно было бы обращаться как с вьюхой или табличным мапом, то можно было бы всегда ее в коде использовать.

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

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

Last edited by Logger; 19.05.2017 at 11:38.
Old 19.05.2017, 11:37   #5  
mazzy is offline
mazzy
Участник
mazzy's Avatar
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Join Date: 29.11.2001
Location: Москва
Blog Entries: 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.
Old 19.05.2017, 11:39   #6  
fed is offline
fed
Moderator
fed's Avatar
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,913 / 5736 (197) ++++++++++
Join Date: 13.03.2002
Location: 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
В общем - в зависимости от мощности вашего сервера оно может сработать, а может и не сработать
This post has been rated by: Logger (3).
Old 19.05.2017, 11:41   #7  
mazzy is offline
mazzy
Участник
mazzy's Avatar
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Join Date: 29.11.2001
Location: Москва
Blog Entries: 10
Quote:
Originally Posted by fed View Post
Можно посмотреть на sysComputedColumn и примеры его использования.
это конечно да... но количество модификаций, которое нужно сделать и протестировать будет очень большим.
мне кажется, что для грязных данных. это какой-то перебор.
__________________
полезное на axForum, github, vk, coub.
Old 19.05.2017, 12:06   #8  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Join Date: 12.10.2004
Location: Москва
Blog Entries: 2
Основная проблема как мне кажется - научить вьюху отбирать из InventSumDelta записи с нужным TTSid - актуальным для текущей сессии.

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

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

Last edited by Logger; 19.05.2017 at 12:09.
Old 19.05.2017, 12:17   #9  
fed is offline
fed
Moderator
fed's Avatar
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,913 / 5736 (197) ++++++++++
Join Date: 13.03.2002
Location: Hüfingen,DE
Можно еще context_info использовать. Указывать контекстную информацию в postTtsBegin() и очишать в preTTSCommit()
Old 19.05.2017, 12:44   #10  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Join Date: 12.10.2004
Location: Москва
Blog Entries: 2
Да точно.
Я тоже сперва про нее подумал, но потом решил отказаться. У нас в реестре включен флажок (Мониторинг работы), по которому ядро в эту переменную пишет разную служебную инфу. Боюсь пересекутся.

Last edited by Logger; 19.05.2017 at 12:46.
Old 19.05.2017, 13:16   #11  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Join Date: 12.10.2004
Location: Москва
Blog Entries: 2
Пример с 1-го раза не вложился.
Attached Files
File Type: zip InventsumDeltaExample.zip (9.2 KB, 148 views)
Old 22.05.2017, 22:26   #12  
Ярослав Щекин is offline
Ярослав Щекин
Участник
 
78 / 174 (6) ++++++
Join Date: 16.03.2009
Quote:
Originally Posted by Logger View Post
Основная проблема как мне кажется - научить вьюху отбирать из InventSumDelta записи с нужным TTSid - актуальным для текущей сессии.
Хмм... я правильно помню, что вне транзакции InventSumDelta всегда пустая, т.е. она всегда очищается по завершениии транзакции?
Далее, для запросов (без forupdate) в Ax2012 всё ещё используется Read Committed Snapshot Isolation?
Если всё это так, то "чужие" записи в ней просто невозможно увидеть, т.е. условие по ttsId, казалось бы, просто не нужно (оно лишь оптимизирует выборку)...
This post has been rated by: Logger (3).
Old 23.05.2017, 09:20   #13  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Join Date: 12.10.2004
Location: Москва
Blog Entries: 2
На первый взгляд это так, но как-то это ненадежно. Высок риск получить блокировку. Т.е. для поиграться - подойдет, а на продуктиве как-то стремно писать код который закладывается на такие вещи.
Tags
ax2012, inventsum, inventsumdelta

 

Similar Threads
Thread Thread Starter Forum Replies Last Post
Множественные запросы по 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

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 15:40.
Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Contacts E-mail, Advertising.