01.09.2018, 14:11 | #1 |
Участник
|
ievgensaxblog: One more reason to avoid global variables
Источник: https://ievgensaxblog.wordpress.com/...bal-variables/
============== You can find tons of articles and discussions on the web why global variables should be avoided in any programming language. Here is another one that is AX specific. Recently, I had to deal with a heisenbug and when I got to the bottom of it, I realized that anyone could do the same rookie mistake. I did a quick search and found at least one in standard application, so it’s worth to share and maybe you need to fix it in your code as well! This bug is related to SysGlobalObjectCache. It is recommended to use it for better performance. To create an entry in the cache we need scope, key and value. Usually we use fixed scope for each task type (i.e. CustVendExternalItemDescriptionExistsCheck). Key usually is a record Id we are searching in DB (i.e. “0001”) and value is a data returned from DB (i.e. InventTable record). But we often forget that records in different legal entities could have same id and result cached in one company is not valid for another company! Let’s look at an example. On standard demo data I found an item that has same id (0001) in 2 companies (usrt, frrt). I added external description for it only in one company (usrt). Now I’m using standard findExternalDescription() method of VendExternalItemDescription class that returns external item description. Under the hood it checks if there is a record for given item and vendor combination and caches the result to avoid extra database calls. In the test job bellow first call to findExternalDescription() method caches false because there is no description for given key. Then I switch to the company where I have a description, but method still returns false because there is an entry in the cache. When the cache is cleared method finally returns true because it does actual search in DB. class RunnableClass1 { public static void main(Args _args) { ItemId itemId = ‘0001’; VendAccount vendAccount = ‘1001’; inventDimId inventDimId = ‘AllBlank’; changecompany(‘frrt’) { //search for an item description. False is cached because no description exists boolean found = new VendExternalItemDescription(itemId, InventDim::find(inventDimId), vendAccount).findExternalDescription(); info(queryValue(found)); } //change company to company where description exists changecompany(‘usrt’) { boolean found = new VendExternalItemDescription(itemId, InventDim::find(inventDimId), vendAccount).findExternalDescription(); //false is returned because it is cached from previous call info(queryValue(found)); //reset cache SysGlobalObjectCache::clearAllCaches(); found = new VendExternalItemDescription(itemId, InventDim::find(inventDimId), vendAccount).findExternalDescription(); //true is returned after cache flush info(queryValue(found)); } } } As you can see, it’s very easy to create similar issue or maybe you already have one, because it is data specific and we rarely test our customizations using multiple companies. From another side, it is even easier to fix it, just add DataAreaId to the cache key! Источник: https://ievgensaxblog.wordpress.com/...bal-variables/
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|