Some folks want to know how they can follow the progress of a query from initial execution on the client through to the server and back. Sometimes they just want to watch. Sometimes they want to intervene.
DevForce raises a number of events along that path to which you can subscribe. You can learn about them from our documentation and by examining the Reference Help. Just thought I'd draw your attention to ones that stand out in my mind.
What I write is "true" at the time of writing which is release 5.2.2. I'm making no attempt to tell the full story; just the bits that are juicy to me.
The events I'll discuss are the ones raised on the client.
Client-side Events
Client events are raised by the IdeaBlade.EntityModel.EntityManager and that's where we'll start. I'll discuss four:
- Querying
- Fetching
- Fetched
- EntityServerError
Querying
Querying is raised when the EM is about to "execute" the query, regardless of whether the query will be satisfied from the cache or require a trip to the server. Handlers receive an EntityQueryingEventArgs which provides the query and the opportunity to cancel the query ... right now.
You can modify the query (e.g., add filters) or completely replace it. If you cancel, the manager will return a null entity or an empty entity list (assuming the query is designed to return entities).
Let the EntityManager continue to evaluate the query. If it can satisfy the query entirely from the cache, no more events are raised; the result is returned.
There is no Queried event; your query result is your notification.
Fetching
Suppose the EM cannot satisfy the query from its entity cache. The EM will have to go to the server. It raises the Fetching event just before doing so .
Fetching handlers receive an EntityFetchingEventArgs which provides the (potentially revised) query and the opportunity to cancel the query ... right now.
If your Fetching handler is called, you know that the EM is about to send a query request to the server. You can stop it by canceling ... and the EM will return some kind of "nothing" to the caller just as it would have had you canceled in a Querying handler.
The query you receive may not be the same as the initial query ... even if you did nothing to change it in a Querying handler. DevForce may have determined that it could satisfy some of the query request from the cache and will have narrowed this query to fetch a more limited set of server data. Take heed of this difference and capture the original query in a Querying handler if it is important to you.
Fetched
Let the EM proceed. It sends the query to the server. If the server succeeds, it returns the results to the EntityManager. Upon receipt, the EntityManager merges those results into its entity cache and raises the Fetched event.
Fetched handlers receive an EntityFetchedEventArgs which provides the query (see Fetching event) and something called "Result".
"Result" is not the result of the original query. It is the result of the query operation performed on the server. It contains every entity the server returned to the EM ... and only those entities.
Imagine a query for Orders which included a "span" to get the related OrderDetails as well. Then both the retrieved orders and their associated retrieved orders will be in "Result". Later, when the EM return to the caller, it will return only orders ... because that is what the query was about. But here and now is the moment to observe (and modify) all entities returned from the server, whether or not they will be returned to the caller.
With these results hand, you can modify them, remove them from the cache, add to them, and do most any sneaky thing that crosses your mind.
Note this: the caller may still receive entities although the EntityFetchedEventArgs.Result is empty! Most normal queries are applied both to the entity cache and to the server-side data source. The caller receives a blend of these two entity sources. Your fetched handler only receives material that came from the server. The server might have returned nothing while the cache contributed some entities ... and the final result to the caller will consist of the cache-sourced entities.
EntityServerError
If the manager sends a query to the server for processing and the server fails to return a result (exception, timeout, lost connection, etc.), the Fetched event will not be raised. The EntityManager will raise an EntityServerError instead.
Your EntityServerError handler receives an EntityServerErrorEventArgs holding the exception. The exception will be a DevForce EntityServerException that you can analyze for the cause; the inner exception will likely hold some useful server-side information.
If you set EntityServerErrorEventArgs.Handled to "true", that's the end of it. If you don't set Handled to "true", the caller can catch the EntityServerException ... or not. If the original call was an Async query execution, the exception can be found in the argument passed into the callback.
If handled, the caller will receive a "nothing" result as if the query had been canceled.
Server-side Events
There are a couple of "events" raised on the server during this process.
- EntityServerFetching
- EntityServerFetched
These aren't really "events" in the .NET sense. What actually happens is that DevForce looks inside the server-side probe assemblies for classes that implement IEntityServerFetching and IEntityServerFetched. Such classes implement OnFetching and OnFetched methods that take EntityServerFetchingArgs and EntityServerFetchedArgs respectively.
DevForce calls them before and after presenting a query to the data source provider giving you the chance to manipulate the query or perform some post-fetch processing on the server before returning results to the client. You can also cancel the query on the server or terminate it by raising an exception in one of these handlers.
For example, you might cancel the query in an EntityServerFetching handler if you determined that the client lacked authorization to perform the query (alternatively I might throw an exception so I could send back a security violation). The documentation speaks to this scenario.
This post is already long; I'll pick up on these Server-side events another time if folks want to know more.
Client Query Events Payoff
With these events you can identify (and report)
- the original query
- whether the manager had to go to the server for data
- what query it used to go to the server
- what material came back from the server
- what material came from cache (by subtraction)
- exceptions thrown by the server
You can also tweak the query and the results along the way.