Accordingly, please take note: the MergeStrategy is not the same across all of the pre-wired QueryStrategies.
Lesson #1: Check out all aspects of the QueryStrategy before you use it. The QueryStrategy today consists of three parts
· FetchStrategy (how and when the EntityManager goes to data source and the cache)
· MergeStrategy (what to do when a retrieved entity is found in the cache)
· QueryOptions (other dials)
Lesson #2: You may want to create your own QueryStrategies so that they fit your expectations and are used consistently everywhere.
The following is the email thread of my journey to enlightenment. Hope you will find the tale cautionary and instructive.
------
Sent: Tuesday, August 11, 2009 2:26 PM
To: Ward Bell
Subject: RE: DataSource test
Both of these tests pass...
[TestMethod]
public void DataSourceNormalTest()
{
//
// TODO: Add test logic here
//
var _dm = DomainModelEntityManager.DefaultManager;
var nancy = _dm.Employee.Where(
e => e.LastName == "Davolio" ).First();
var originallastname = nancy.LastName;
nancy.LastName = "Smith";
var nancy4q = _dm.Employee.Where(e => e.LastName == "Davolio");
nancy4q.QueryStrategy = QueryStrategy.Normal;
var nancy4 = nancy4q.FirstOrNullEntity();
var lastname4 = nancy4.LastName;
Assert.IsTrue(nancy4.EntityAspect.IsNullEntity);
}
[TestMethod]
public void DataSourceThenCacheTest()
{
//
// TODO: Add test logic here
//
var _dm = DomainModelEntityManager.DefaultManager;
var nancy = _dm.Employee.Where(
e => e.LastName == "Davolio").First();
var originallastname = nancy.LastName;
nancy.LastName = "Smith";
var nancy4q = _dm.Employee.Where(e => e.LastName == "Davolio");
nancy4q.QueryStrategy = QueryStrategy.DataSourceThenCache;
var nancy4 = nancy4q.FirstOrNullEntity();
var lastname4 = nancy4.LastName;
Assert.IsTrue(lastname4 == originallastname);
}
----
From: Ward Bell
Sent: Tuesday, August 11, 2009 3:06 PM
Perhaps you’ve discovered a bug. You have at least discovered anomalous behavior that deserves justification.
In your second “DatasourceThenCache” test you look for “Davolio” and find her in the database. You merge the changes … whereupon it is evident that she (employee.Id==1) is “Smith”. After the query has been run against the cache (as part of the “…ThenCache” phase), I would have expected it to return a null entity … because there is no “Davolio” in the cache.
In other words, “Normal” and “DatasourceThenCache” should return the same result. The only difference should have been that “DatasourceThenCache” made a trip to the database.
What is wrong with my expectation? I thought that “DatasourceThenCache” should be understood as follows:
· Force query on the database
· Merge results with the cache
· Ignore the database query results
· Re-apply the query as if cache-only
· Return the cache-only query results
That is obviously not happening if the second query below returns a non-null entity.
--
From: Ward Bell
Sent: Tuesday, August 11, 2009 8:48 PM
My comments back to the chief architect
--
Sent: Tuesday, August 11, 2009 6:05 PM
To: Ward Bell
Ward
This is the same as it was in Classic and …. It makes sense. If you are querying “DataSourceOnly” wouldn’t it confuse you if you queried for “Diavolo” and had “Smith” returned?
EXACTLY. Which is why I thought it should return NULL ENTITY
Which is what would happen if we had the MergeStrategy for “DataSourceOnly” be PreserveChanges. The main idea behind DataSourceOnly is that you get the entities as they look in the database.
I would rather have NULL ENTITY than risk reversing the user’s changes. I concede that reasonable minds may disagree about which is worse. The KEY THING is to know what you’re doing. I’m sure we document it. Like everyone else, I ignore the documentation, fail to test my assumptions, and then I get bitter about it. J
Edited by WardBell - 12-Aug-2009 at 12:31pm