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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 23.01.2017, 13:27   #1  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,759 / 3627 (178) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Поговорим о Unit Of Work?
наткнулся на
https://www.youtube.com/watch?v=cm64vkwzxl4
SMART TALKS: Dynamics AX мероприятие

что думаете о реализации класса UnitOfWork в Аксапте?
что думаете о реализации UnitOfWork по сравнению с InventSumDelta?


в комментариях к видео я написал:
паттерн Unit of Work: https://martinfowler.com/eaaCatalog/unitOfWork.html
полностью паттерн реализован в .net Entity Framework.
в аксапте достаточно ограниченная реализация.

основное преимущество не в многопоточной вставке, конечно.
основное преимущество в комбинации методов обновления и ЧТЕНИЯ (getByKey)
особенно когда записи обновляются несколько раз.

пример - inventTrans.costAdjustment обновляется каждый раз, когда происходит вставка в InventSettlement. по идее нужно делать inventTrans.update в базе каждый раз.
кроме того, есть InventSum, который нужно обновлять каждый раз как только изменяется/добавляется запись в InventTrans.

с Unit of work можно сделать алгоритм, который:
1. читает inventTrans из базы один раз.
2. обновляет в памяти
3. читает обновленную версию из памяти
4. в самом конце делает команду обновления в базу.
таким образом, сильно сокращается число обращений к базе. за счет этого и происходит оптимизация.

главная особенность:
getByKey читает запись из памяти, а если записи в памяти нет, то метод самостоятельно читает из базы.
за счет этого и достигается унификация алгоритма и щастье программиста.

особенности:
  • unit of work имеет смысл использовать в рамках одной транзакции
  • unit of work аксапты абсолютно не приспособлен для взаимодействия с bulk-операциями (хотя в .net этот паттерн взаимодействует с LINQ). unit of work в аксапте имеет смысл использовать в режиме "работа с отдельными записями".
  • unit of work в аксапте абсолютно не приспособлен для работы с формами. по сути каждая форма сама по себе "умный" unit of work.
  • в аксапте нет возможности управлять размером буфера unit of work. поэтому на огромных транзакциях типа закрытия склада класс unit of work может ухудшить ситуацию. Хотя именно для закрытия этот класс и создавался.

ну, и конечно Unit of Work в своем изначальном виде во внеаксаптовском мире часто используется как data source для unit test'ов.

Последний раз редактировалось mazzy; 23.01.2017 в 13:42.
Старый 23.01.2017, 15:41   #2  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,178 / 4000 (138) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Касательно InventSumDelta и закрытия склада - там не все так просто. Там запросы на обновление написаны достаточно хитро, с тем чтобы предотвратить дидлоки. Сначала все записи, подлежащие обновлению, блокируются, а потом чохом обновляются. Встроенный механизм про блокировки, планы исполнения, дидлоки и тд и тп ничего не знает (и вряд ли его особо удастся обучить этому делу). С учетом этого - я сомневаюсь что этот механизм применим для обновления inventSum или закрытия склада. Для того чтобы этот шаблон был работоспособным, он должен на уровне SQL Server поддерживаться, а не на уровне сервера приложений. Кроме того - не очень понятно что делать в многопользовательской среде. Например - если у нас на лету кто-то другой запись удалил, что с UnitOfWork делать ?
Старый 23.01.2017, 15:48   #3  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,759 / 3627 (178) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
про удаление:
Цитата:
Сообщение от mazzy Посмотреть сообщение
unit of work имеет смысл использовать в рамках одной транзакции
вне транзакции - это "выстрелить себе в колено"

про планы запросов и deadlock:
Цитата:
Сообщение от mazzy Посмотреть сообщение
в аксапте достаточно ограниченная реализация.
"ограниченная" в смысле интеллекта.
тупенький алгоритм, в общем ))))

поэтому и спрашиваю.
Старый 23.01.2017, 15:52   #4  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,178 / 4000 (138) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Цитата:
Сообщение от mazzy Посмотреть сообщение
про удаление:

вне транзакции - это "выстрелить себе в колено"
Вероятно - ты хочешь сказать "В рамках транзакции и с пессимистическими блокировками". Потому что если мы дофига всего насчитаем в памяти, а потом в момент записи выяснится что работали мы на неактуальных данных, то ведь придется все перезапускать и пересчитывать...
То есть - по большому счету - этот паттерн применим к данным, у которых малая степень конкуренции. Например - заказах на продажу. Все-таки шансы что несколько сейлов вдруг продают один и тот же заказ - пренебрежимо мала...
P.S. Хотя с другой стороны - если ты хочешь кэширование, то явно ситуация несовместима с многопользовательским доступом и блокировками. Так что может это все и полезно - но для довольно ограниченного набора ситуаций...

Последний раз редактировалось fed; 23.01.2017 в 16:11.
За это сообщение автора поблагодарили: mazzy (5).
Старый 23.01.2017, 16:53   #5  
ax_mct is offline
ax_mct
Участник
Аватар для ax_mct
 
1,723 / 556 (22) +++++++
Регистрация: 10.10.2005
Адрес: PHP
Кажется этой ссылки еще не было:
https://blogs.msdn.microsoft.com/sav...series-part-5/
Цитата:
Although the number of insert calls remain 20k, the time fall down from 5 seconds to 1.5 seconds. Now we are more than 3 times faster than the naïve approach that calls the insert statement 20k times through a loop.
Цитата:
  • UnitOfWork must run on the server tie
  • The child must have a relation explicity defined in AOT to the parent
  • No record will be inserted into the database until the saveChanges method is called.
  • You can enjoy the methods: insertOnSaveChanges, deleteOnSaveChanges, updateOnSaveChanges, saveChanges
Фича, да. Но я бы не применял по умолчанию пока не поставлена отдельная задача по улучшению производительности и тогда рассматривал бы как одну из опций. Так как какие-то риски все равно есть, а в первоначальных решений их надо сводить к минимуму.

X++:
public static server void insertWithUnitOfWork()
{
    FooChild   child;
    FooParent  parent;

    // Instantiating the UnitOfWork.
    // Notice that this method runs on server
    UnitofWork unitOfWork = new unitOfWork();
    int i;

    for (i = 0; i < 10000; ++i)
    {
        parent.ParentId = int2str(i);
        parent.Name = 'Any name for parent' + int2str(i);
        parent.Description = 'Any description for parent' + int2str(i);

        child.ChildId = int2str(i);
        child.Name = 'Any name for child' + int2str(i);
        child.Description = 'Any description for child' + int2str(i);

        // You will just be able to call this method if there is a relation
        // called FooParent at FooChild table
        child.FooParent(parent);

        // Marking these buffers to be inserted by UnitOfWork
        // The buffers are not being inserted at the database right now.
        unitOfWork.insertonSaveChanges(parent);
        unitOfWork.insertonSaveChanges(child);
    }

    // Finally, asking UnitOfWork to insert the records at the database.
    unitOfWork.saveChanges();
}
За это сообщение автора поблагодарили: mazzy (2).
Старый 23.01.2017, 17:19   #6  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,178 / 4000 (138) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Еще как-то я не уверен в многопоточной вставке. В документации ничего об этом не говорится. Кроме того - для просто быстрой множественной вставки система вполне может использовать Array Binding. Просто одному оператору insert передается сразу много строк для вставки, без всякого паралелизма..
Старый 23.01.2017, 18:04   #7  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,759 / 3627 (178) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Но я бы не применял по умолчанию пока не поставлена отдельная задача по улучшению производительности и тогда рассматривал бы как одну из опций.
Боюсь, что тут либо, либо.

Алгоритм может решить послать новый запрос в SQL и, тем самым, запросить выборку заново.
тогда выборка из базы и выборка из unitOfWork - две большие разницы.

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

Или, например, сопоставление по клиенту/поставщику. Там query().reset() происходит практически после каждого чиха.
За это сообщение автора поблагодарили: ax_mct (2).
Старый 23.01.2017, 18:20   #8  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
384 / 161 (6) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
по теоретической части двух центов не имею, но могу поделиться практическим опытом.

успешно воспользовался unit of work при импорте из экселя новых цен поставщиков, когда нужно было сначала создать "заголовочные" записи для основной цены как бы виртуально, а потом к ним "привязать" несколько десятков подчинённых строк с вариациями цен для цвета, размера и проч.

обычный импорт тянулся неимоверно долго, после применения unit of work всё стало загружаться в секунды.
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
За это сообщение автора поблагодарили: mazzy (2), ax_mct (2), gl00mie (2).
Старый 23.01.2017, 19:50   #9  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от wojzeh Посмотреть сообщение
обычный импорт тянулся неимоверно долго, после применения unit of work всё стало загружаться в секунды.
А почему обычный импорт так долго шел ? На чем потеря была ?
Старый 23.01.2017, 19:55   #10  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
384 / 161 (6) ++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от Logger Посмотреть сообщение
А почему обычный импорт так долго шел ? На чем потеря была ?
ну, есть разница между прогнать N раз цикл по "заголовкам" и M раз по "строчкам" или дробить "строчки" на N циклов, сохраняя каждый раз "заголовок"
__________________
Felix nihil admirari
-----------------------------------------------------------------------------------------------
AX2012
Старый 23.01.2017, 21:48   #11  
DAX is offline
DAX
Участник
 
25 / 18 (1) ++
Регистрация: 03.12.2008
Из личного опыта:

Не получилось запусть doUpdate() . Может это и фишка конечно.

Не получилось достать уже добавленные данные (getByKey() не работал, хотя выше пишут что работает. Наверно я что-то не так делал).

Различные проблемы с update conflict. Например запихнуть 2 записи и если update() первой записи обновит вторую, UnitOfWork вылетит.

По-моему были проблемы если 2 раза одну и ту же запись добавить. Данные из первого буфера в базу уходили, но надо проверить.

Кстате, а пример с добавлением 10к записей пробовали запускать в транзакции? Вроде уже и не такая большая разница
За это сообщение автора поблагодарили: mazzy (2).
Старый 24.01.2017, 10:39   #12  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,178 / 4000 (138) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
В общем - по итогам чтения дискуссии, у меня появилось впечатление что UnitOfWork в Аксапта - это просто расширенная и слегка недоведенная версия RecordInsertList, а вовсе даже не реализация классического паттерна.
Старый 24.01.2017, 10:54   #13  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,759 / 3627 (178) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Цитата:
Сообщение от fed Посмотреть сообщение
впечатление что UnitOfWork в Аксапта - это просто расширенная и слегка недоведенная версия RecordInsertList, а вовсе даже не реализация классического паттерна.
расширенная:
1. поддерживает несколько таблиц
2. умеет читать

недоведенная - да. прежде всего в аксаптовской части.

и будешь смеяться - именно реализация классического паттерна. остальные реализации не сильно лучше.

просто этот паттерн мало предназначен для серверной части приложения. этот паттерн отлично работает на клиентской стороне (если ему не надо взаимодействовать с другими библиотеками доступа к данным).
Старый 24.01.2017, 13:41   #14  
Napalm is offline
Napalm
Участник
 
75 / 76 (3) ++++
Регистрация: 23.05.2012
Я бы добавил в особенности что нельзя использовать при работе с несколькими компаниями.
За это сообщение автора поблагодарили: mazzy (2).
Теги
unitofwork, полезное

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
axmfg: Rounding up work for raw material picking to the nearest handling unit Blog bot DAX Blogs 0 20.01.2016 22:13
DynamicsAxSCM: WHS Work List Blog bot DAX Blogs 0 19.06.2015 15:11
DynamicsAxSCM: How to support a case picking operation using wave containerization in AX2012R3 Blog bot DAX Blogs 0 19.11.2014 16:11
axmfg: Replacing work order types for production output in CU8 Blog bot DAX Blogs 0 12.09.2014 18:12
axdaily: Unit of Work Blog bot DAX Blogs 4 05.05.2011 11:54
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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