Content Cache dependency in Kentico V9 - kentico

I want to update cached content of one custom table when another custom table item is updated.
Let's say I have two Custom Tables: Product and Order.
There are List and Edit pages for both Product and Order.
In DB there is a trigger on Product that updates some data on Order if Product is changed.
My scenario is, when I update lets say Product 1(one of the item of type Product), I want Orders (all orders) cache to refresh and reflect changes made in DB for Order. This is not happening right now.
Global settings are 10 minutes for content caching. But somehow it takes 20 minutes to reflect changes. Not sure why.
Also on Orders' CustomTableRepeater's System Settings->Cache minutes is set to 0 means it should not be caching content at all but it still does so I am at loss here
Answer to this scenario would be setting cache dependency dummy key as per Kentico documentation.
My questions are:
Do I set dependency key of all orders on Product's edit page's web part partial output cache dependency property?
for e.g. orders|all
Will this refresh all order records cached in for custom table data source when any product is modified?
Or I set dependency key of all Products on orders' repeater's System settings->Content Cache Dependency property?
for e.g. products|all
Please note Cache minutes property is set to 0 so ideally this content should not be cached.
Or add above key to Order's Edit page's webpart's partial output dependency?
Also for custom table how to get proper dummy key? Is it
products|all
OR
nodes|corportateside|products|all
OR
customtableitem.products|all
Or I need to add pages' dummy keys that I can see in debug->cache settings?
I have tried setting up all these things but nothing seem to work.
Any help is greatly appreciated.

Okay so it turned out to be a not cache issue.
I was able to resolve my issue. Putting answer here for future reference I will first list down what I tried:
Installed Hotfix
Add Partial Cache Dependency key
Add Cache dependency key for Content caching. Nothing worked.
Got an idea by reading answer from this questions: https://devnet.kentico.com/questions/kentico-8-2-database-caching
When I was updating CustomTable A's data, in DB trigger on A would update data in table B which I needed to refresh in Site's cache.
When I tried 'Clear Cache' from Debug application from Admin, it still did not update data in Site. Also my Custom Table data in Admin was also not getting updated.
So reading one answer from above question, I realized I need to refresh Hashtables for data to be refreshed in admin and subsequently in site.
So I added code to CustomTableForm.aspx.cs in OnAfterSave event handler. Here I am checking if current CustomTable is my table A, then refresh hashtables of B.
This worked.

Related

How to log last changes in hybris when the new feed/ feeds updates come through

I'm aware that Hybris have savedvaluesmodel and savedvalueentrymodel to capture last changes of the data model and its attribute value whatever has changed recently, and it also maintains the history.
And this works only if we are modifying the data after login into Backoffice and this doesn't seem to work in case of feeds which comes via HotFolder. I'd like to know, is there any provision which comes with Hybris out of the box to capture the same information or changes that was done for a given data model through feed?
What I have observed based on OOTB code is ,this class DefaultItemModificationHistoryService is responsible for logging the changes (populate the values and saved the last changes into the saved values model table) that was done at the model level, and this is located inside the OOTB Backoffice extension and this extension is already extended by myprojectbakcoffice extension which further extends myprojectcore extension.
In order to capture the last changes done via feed we thought of handling that logic in an interceptor, however the above class isn't accessible in our myprojectcore extension as it's declared in Backoffice.
What are the other possible solutions that I can think of in order to implement this?
Found some article related to this in here.
Please advise.
You can use the hybris commerce audit framework to log all of the changes happening in the system.
The documentation here says, "Generic audit tracks every persistence action, including creation, modification, and deletion for specified types. The audit is stored as a change log that allows you to see how an item changed over time."
But this comes with a DB overhead. There are specific tables that gets heavily logged with the details of the changes.
These tables have a naming convention as <item_type>_sn.
E.g.: For Order item type, the audit table would be auto created as orders_sn
This is why it is always advisable to turn off the audit as applicable.

Updating data on rows deleted event

I have a custom page with a form and a grid. When a row from a grid is deleted, I want to update some other rows. I am therefore handling the rowdeleted event. I confirmed (through debugging) that the event is firing correctly and that the data is being updated correctly.
The only issue I have is that the screen still shows the old values. My delete row correctly disappears but the other rows do not get updated.
For each row that I change, I am calling the Update method of the Data View. However, this still does not refresh the user interface.
Interesting, if I save, all my changes get correctly updated to the database. Which confirms that this is a UI isssue.
Is there any additional step that I need to perform to refresh the user interface? Or should I just avoid doing updates in Row Deleted event?
To guarantee constant optimal performance level, in the end of a roundtrip grids in Acumatica only update currently selected record. This behavior is by default. In case you insert/update/delete other records in the same grid within an event handler or an action delegate, it's always necessary to call View.RequestRefresh() to force the grid to update its entire content instead of only the selected record.
I managed to solve the issue by calling View.RequestRefresh(). However, I am not sure whether this is a standard practice. But I did find it used in several places in the Acumatica code

Deployment type-code changed from Reserved Hybris to Non-reserved codes. Do I need Update or Initialize the whole system?

I used some of the Hybris reserved Deployment code and then later changed to non-reserved deployment type codes. Do I need to Initialize the system in-order to reflect the changes with new deployment code or just an Update works. There are many items that deployment code has been changed. Why update doesn't work?
When you use a reserved code in your deployment table, you're likely to add the attributes of your object in an existing table. If you have attributes with the same name, it'll surely be a mess in the table (I don't know how hybris will choose the table type for example).
When you run an update with the good deployment code, it will create a new table which is just fine. The other table which has been used by two objects will still remain potentially broken because hybris won't delete any column.
That's why you should initialize your system to have a clean DB. The issue is that you'll lose all your data.
If you need to migrate data it will be probably quite hard because you must have to look on the broken table and distinguish between the attributes that should not be there and the others. So I hope for you that it's just a dev issue!
Actually i would suggest you to do initialize rather than update more likely that the update will not work for you in this case and probably you will get some error messages saying invalid pk xxxxxxxxxxxx because of unknown typecode yyyy.
As you may know the typeCode (deployment code) is an essential operator for the generation process of PKs in Hybris and thanks to it Hybris can ensure the uniquenessity of the PKs, so even if you change the old typeCode with a new one it's very likely that Hybris will still keep the old typeCode somewhere hence PKs already generated will never be consistent with the new typeCode.
So that's why you should never change the typecode of an item once given.
My suggestion is :
To make a backup of your existing data (you can export it from HMC,
you may take a look at alain.janinm's answer here).
Then initialize your System.
Then re-import the data again.
Note : that typecodes between 0 and 10000 are already reserved for hybris
particular items.

Update Kentico document field regardless of versioning

I have a field on one of my base page types which I need to update programmatically from an external data feed, so that it can be included in my Smart Search index.
The documents are versioned, but I want to update the published value of this field regardless of checkout state, and obviously avoid any sort of overwrite when documents are checked in.
The field will not appear on the editor form -- or ideally, would conditionally display for Global Admins.
It appears that using the API to update the document without doing a CheckOut fails silently. However if I do a Checkout/Update/CheckIn on a checkout-out page, the author will lose their work I assume?
Any way to handle this "versionless" field via the Kentico data model and API?
I don't think there is a way around updating checked out pages. You can update the page type table directly, but as you mentioned, it will be overwritten when they check in. You could update the version history I believe to make changes to the current data that is checked out, but again, I think that will be lost if the user cancels.
The only way I can think of to solve your issue is to create another table that maps the values you want to the page. Then you don't have to worry about the pages being checked out, you just need to grab the documentID or something. Since the value isn't displayed to the editor, you just have a field that does a lookup on this table.
The preferred and right way is using the API but as you stated, it causes problems if a user has something already checked out and working on it or it's in workflow and not published yet.
If the field you're updating is page type specific, there is one thing specifically I can think of and that's going directly to the database to the page type's database field and perform an update to that field.
Note: this is not recommended unless you know specifically what you're doing and have done full testing on it
The down side of going direct to the database is this will not update the current version since you're using check in/out and workflow. You will also need to update the checked out and current version which means you need to:
Go to the Document itself in the cms_documents table and get the document you are working with.
Then using the fields DocumentCheckedOutVersionHistoryID and DocumentPublishedVersionHistoryID' you can get the version history IDs of the document from theCMS_VersionHistory` table.
Then you can perform an update to the CMS_VersionHistory and your custom page type fields.
You will then need to look in the CMS_WorkflowHistory table and find out if that document is in workflow and in what step.
After you have that workflow history step, use the VersionHistoryID field to go back to the CMS_VersionHistory table and update that record with your data.
Again, not an elegant solution since you are using check in/out and workflow but after some trial and error and testing you should be able to figure it out.
UPDATE
You may also be able to add a custom table or some other linked database table which will allow you to create a global handler. The linked table would be where you perform your updates via API and other calls without versioning or workflow. Then when a user updates a specific page type you could do a check to see when the last time that linked table was updated and update the field(s) you need on update of that particular page (of course by node and document IDs).
Unfortunately you'll have to check it in and out with API. See examples here.
Also you might need to publish it in order to reflect changes on the live site.

Kentico - WHERE condition for custom Page Types page

I have a custom page type for employees, and one of the fields is Location. I want to show/filter only employees in "San Jose" or "San Francisco" and used this WHERE condition below but it didn't work. Apparently, I missed something very basic. Could you help?
Location LIKE '%San%';
I did another test, where instead of page type, I used custom table with the exact field names and was able to filter using the same statement. On a related note, I'm new to Kentico and exploring which is more suitable for creating/maintaining a list of about 100 employees - Page Types or Custom Tables - with the ability to filter by department, location etc. Appreciated your input here as well. Best!
If you're adding the WHERE condition into a standard Kentico repeater or other data source, the syntax looks right except you do not need the semicolon ";".
You'll also want to double check the field name, and if you are limiting your query to certain columns (as is best practice especially for larger data sets) and be sure the field you are filtering on is being selected.
Regarding the management of your employee list, either method you've described will work. In that scenario it typically depends on who will be editing the content, and how frequently. It is more editor-friendly, in my opinion, to add those documents into the content tree. This also gives you quicker control over the order, and keeps it similar to how other content on the site is maintained. I also like to set up folders or other parent page types as categories if needed, so the documents can be dragged and dropped between them and it sets up a visual taxonomy that isn't possible if it's all stored in a table. Storing items in the tree also allows for workflow and versioning, as well as more granular control over permissions/access, if this is important to you.
It's awesome that you are thinking about how to best store your data in advance. There many factors to consider such as overall number of records, number of columns, the fact whether you need to use workflow, versioning, preview etc..
The best source of information regarding this would be this article which summarizes all options you have and gives clear explanations of which to use in which scenario.
And to your original question - What components are you using to display the data? Is the repeater? If so, can you make sure to set the Page types property to match the page type you are displaying? If the page types is not configured, Kentico will not load any custom fields because it doesn't know from which table it should load the data from.
Additionally make sure to either include the "Location" field in the Columns property or leave the columns blank (not recommended because then Kentico loads all columns which is like 200. when you count all from CMS_Document, CMS_Tree etc..)
Below is the framework that I use to debug whenever I wish to add a repeater and is facing some problem.
First get all the columns instead of accessing limited columns. Fetching all columns will make sure that I don't have any problem retrieving data.
If I am missing any particular column information name, then I would double check the column name.
I verify this by firing up SQL server management studio and access data from page type table or custom table.
If access to SQL server is not available(generally in Azure hosted solutions with restrictive access to DB), I would enable SQL debug from the settings and see what query repeater is generating to see if it is correct.

Resources