28 Feb 2014

Understanding View Accessors

Introduction
In an ADF application a view accessor is considered as an approach to access a view object from another view object or entity object. The view accessors are mostly used to provide result sets for the lists of values. In this post I am going to show how actually the view accessors work, to reveal what's going on behind the scene, to clarify how many internal view object instances are created by the framework and how many row sets are used.


Internal View Object instances
Let's start with easy things. I've got a view object definition VForexTrade representing forex operations on the currency market. It has an attribute Buycurrencyid with a list of values LOV_Buycurrencyid:


It also has an attribute Sellcurrencyid with a list of values LOV_Sellcurrencyid:



There is a view accessor VCurrency1 which is based on VCurrency view definition.

So there are two LOVs referring to the same view accessor.

And there is an application module TestAppModule with an instance of VForexTrade view object definition. The name of this instance is VTodTrade and it represents today trade operations:



This simple structure can be represented in the following table:
VO instance LOV attribute VA VA View definition Shared VO instance Row Level Binds
VTodTrade Buycurrencyid VCurrency1 VCurrency - true
VTodTrade Sellcurrencyid VCurrency1 VCurrency - true


Since VCurrency1 view accessor doesn't use any shared VO instance, the framework, at run time, is going to create an internal view object instance basing on VCurrency view definition. In this case its name will be like _LOCAL_VIEW_USAGE_VForexTrade_VCurrency1. Note that the name is constructed as a concatenation of view definition names. The VO instance name doesn't matter.

Since the RowLevelBinds property of the view accessor is set to true, the framework, at run time, is going to create a separate non-default row set for each row of the VTodTrade instance. So, the internal view object instance will have a number of row sets like _LOCAL_VIEW_USAGE_VForexTrade_VCurrency1_0, _LOCAL_VIEW_USAGE_VForexTrade_VCurrency1_1,
_LOCAL_VIEW_USAGE_VForexTrade_VCurrency1_2, ...

So, each row in the VTodTrade refers to its own row set providing a list of currencies. But since this list of currencies doesn't really depend on a VTodTrade's row, and VCurrency VO doesn't have any bind variables, all these row sets are backed up by the same query collection. By the first one _LOCAL_VIEW_USAGE_VForexTrade_VCurrency1_0.  That means that the VCurrency's SQL query will be executed only once.  



Let's change this structure a little bit defining a separate view accessor VCurrency2 for the LOV_Sellcurrencyid list of values.
VO instance LOV attribute VA VA View definition Shared VO instance Row Level Binds
VTodTrade Buycurrencyid VCurrency1 VCurrency - true
VTodTrade Sellcurrencyid VCurrency2 VCurrency - true

In this case, at run time, the framework will create another internal VO instance _LOCAL_VIEW_USAGE_VForexTrade_VCurrency2 for the VCurrency2 view accessor. This instance is going to have its own bunch of row sets _LOCAL_VIEW_USAGE_VForexTrade_VCurrency2_0,
_LOCAL_VIEW_USAGE_VForexTrade_VCurrency2_1,
_LOCAL_VIEW_USAGE_VForexTrade_VCurrency2_2, ... .
All of them are going to be backed up the _LOCAL_VIEW_USAGE_VForexTrade_VCurrency2_0 query collection.



So, here we'll have two executions of the VCurrency's SQL query for both query collections.

Let's switch off  the RowLevelBinds property of our view accessors:
VO instance LOV attribute VA VA View definition Shared VO instance Row Level Binds
VTodTrade Buycurrencyid VCurrency1 VCurrency - false
VTodTrade Sellcurrencyid VCurrency2 VCurrency - false

In this case the framework will also create two internal VO instances _LOCAL_VIEW_USAGE_VForexTrade_VCurrency1 and _LOCAL_VIEW_USAGE_VForexTrade_VCurrency2. But each of them will have only one default row set to be shared across all rows of the VTodTrade view object instance. However, the VCurrency's SQL query will be executed twice, since each internal VO is going to be backed up by its own query collection.


Alrighty, let's add one more instance of the VForexTrade to the application module.



Our BC model is represented in the following table:
VO instance LOV attribute VA VA View definition Shared VO instance Row Level Binds
VTodTrade Buycurrencyid VCurrency1 VCurrency - false
VTodTrade Sellcurrencyid VCurrency2 VCurrency - false
VForwardTrade Buycurrencyid VCurrency1 VCurrency - false
VForwardTrade Sellcurrencyid VCurrency2 VCurrency - false

The interesting thing is that nothing is going to be changed, actually. The framework will create the same two internal view object instances with default row sets for each VA definition, and they will be shared by both VTodTrade and VForwardTrade VO instances.






Shared View Object instances

And now let's redefine our view accessors and get them referring to a shared VO instance.
VO instance LOV attribute VA VA View definition Shared VO instance Row Level Binds
VTodTrade Buycurrencyid SharedModule_VCurrency1 VCurrency VCurrency true
VTodTrade Sellcurrencyid SharedModule_VCurrency2 VCurrency VCurrency true

Since the view accessors refers to a real VO instance from some shared AM, the framework won't create any additional internal view objects. Instead of that, it will create a non-default row set within VCurrency shared VO for each view accessor usage with RowLevelBind set to true. And again, there is no any bind variables in the VCurrency and its result set doesn't depend on a row from which it is used. So, all these created row sets are going to be backed up by a single query collection instance. The behavior is pretty similar for both session and application shared AMs. The difference is that in the case of the session shared AM there will be one VCurrency instance per user session, and in the case of the application shared AM the framework will create only one single instance of VCurreny to be shared across the entire application. Besides that, the query collection of a session shared VO can be destroyed due to the AM recycling process or because of the garbage collection process. That will not happen with an application shared VO instance. There is a different mechanism to clean up query collections of the application shared view objects.



 
If we set the RowLevelBind property to false
VO instance LOV attribute VA VA View definition Shared VO instance Row Level Binds
VTodTrade Buycurrencyid SharedModule_VCurrency1 VCurrency VCurrency false
VTodTrade Sellcurrencyid SharedModule_VCurrency2 VCurrency VCurrency false

The framework will create a single default row set for the VCurrency view object, and this row set is
going to be shared for each view accessor usage across all rows.



That's it!

God Save Ukraine!







6 comments:

  1. Very interesting explanation.
    Thanks a lot Eugene.
    I support you and your country for the future ...

    ReplyDelete
  2. this article is toooooooooooo good. Thank you very much Eugene

    ReplyDelete
  3. Thanks, it was quite helpful.

    ReplyDelete
  4. Thanks for the detailed explanation. Can you also explain the behavior when the VA has a bindVariable?

    ReplyDelete

Post Comment