Hi,
I am using DevForce 5.2.6.0.
The folowing is from the product manual for DevForce 2009.
Query Cache
When a EntityManager begins to process a normal query, it checks its query cache to see if it has processed this exact query before. If the EntityManager finds the query in the query cache, it assumes that the objects which satisfy the query are in the entity cache; accordingly, it satisfies the query entirely from the cache without consulting the data source. A one-to-many entity navigation, such as from employee to the employee‟s orders, is translated implicitly to an entity query language (OQL) query that also enters the query cache. The next time the application navigates from that same employee to its orders, the EntityManager will recognize that it has performed the query before and look only in the cache for those orders. The query cache grows during the course of a session. Certain operations clear it as one of their side-effects; removing an entity from the cache is one such operation. The developer can also clear the query cache explicitly. We just said that the EntityManager searches the query cache for an exact match of the current query, but that was really a “little white first approximation.” Actually, the EntityManager does better than that: it searches either for an exact match, or for an unrestricted query returning the same type. If, for example, you have previously retrieved “all Customers” and now ask for “Customers from Canada”, your new query will be satisfied from the cache.
Primary key queries
A query for business objects by primary key may be resolved entirely in the cache. If we search33 for the employee with Id = „1‟ the EntityManager will try to find it in the cache and, if not found there, will only then look for it in the data source. The EntityManager treats navigation along a one-to-one relationship, such as from Employee to HomeAddress, as a primary key query. Navigation in the parent direction along a one-to-many relationship, such as from an OrderDetail to its parent Order, is also a primary key query.
The default QueryStrategy i use is Normal which, if i am not mistaken, uses an Optimized FetchStrategy, meaning that the EntityManager will try to satisfy queries from the cash first and then from the DataSource as long as it finds them in Query Cashe.
I have a business objecr A.
After executing the following code:
DomainModelEntityManager.DefaultManager.A.Execute();
DomainModelEntityManager.DefaultManager.A.Where(f => f.Id == MyId).Execute();
and having the trace viewer and sql profiler open i can see that 2 queries are executed on database, one for each command.
Question 1:
Shouldn't the second query be executed and served from the cashe?
The first query is an unrestricted query returning objects of type A. An exact match for the second query does not exist on query cashe but an unrestricted query returning the same type (A) exists (First Query), so according to the product manual the second should be served from the cash.
Question 2:
I know that A.Id is the primary key for business objects of type A. Does the EntityManager consider the second query to be a Primary Key query? According to the manual "If we search for the employee with Id = „1‟ the EntityManager will try to find it in the cache and, if not found there, will only then look for it in the data source." it should but, please correct me if i am mistaken, it does not. Does the EntityManager consider as primary key queries only navigation queries or can it distinguish when a user searches only by primary key using the Where(Expression<Func<TSource, bool>> predicate) method. What if a business object has a complex primary key?
To make sure that i use the correct query strategy i also tried writing the above commands as:
DomainModelEntityManager.DefaultManager.A
.With(new QueryStrategy(FetchStrategy.Optimized, MergeStrategy.PreserveChanges, QueryInversionMode.On))
.Execute();
DomainModelEntityManager.DefaultManager.A
.Where(f => f.Id == MyId)
.With(new QueryStrategy(FetchStrategy.Optimized, MergeStrategy.PreserveChanges, QueryInversionMode.On))
.Execute();
Thank you in advance,
Kostas.