Hi Paul - Ton of material here. Not entirely sure about your question. I think you are wondering why navigation properties that return lists of entities do not seem to be aware that the material they need is already in cache.
Let's simplify. Suppose you had only four kinds of entities: Product, Color, Supplier, and ProductSupplierMap. You pre-filled the cache with Colors and Suppliers because these are reference entities: there are a handful of each and they are stable. You pre-filled the cache with Products and their ProductSupplierMaps (entities which relate a Product to one or more Suppliers). It would seem that everything that you could possible need to move among these four entity types is waiting for you in cache.
The Product has two navigation properties: Color and ProductSupplierMaps.
The Color property will always be satisfied from the cache because the Product entity holds a foreign key value, the ID of the Color; when you call "aProduct.Color", DevForce looks in the cache for the Color with that product's ColorID, finds it, and returns the Color object.
So it is not true that for "all Navigation Properties ... DevForce still goes to the the DB to fetch the data". Most scalar navigation properties - properties that(a) return 0 or 1 entity - will try to satisfy requests only from the cache. The exception is the "master" entity in a 1-to-1 relationship ... but that's a story for another time.
However, a call to "aProduct.ProductSupplierMaps" will go to the database. "Why?" you ask; "all ProductSupplierMaps are in cache - they are readily available - shouldn't DevForce know that?"
Maybe it should. But it doesn't. There is no information available to the EntityManager that tells it that all ProductSupplierMaps are in cache. YOU know that because you queried for them. And if you issued another query for all ProductSupplierMaps, the EntityManager would dutifully respond entirely from the cache. It can do that because it has seen the query "get all ProductSupplierMaps" before.
But when DevForce sees "aProduct.ProductSupplierMaps" for the first time, it translates this to the query "get all ProductSupplierMaps where the map.ProductId equals this product's Id". This is the first time we've asked for this product's ProductSupplierMaps. The EntityManager has not seen this particular query before. So it must go to the database.
DevForce cannot reason that this second query is conceptually covered by the "get all ProductSupplierMaps" query.
We've thought over the years about extending DevForce so that it could draw that conclusion. We think there are "Enumeration" entities (like "Color") for which this kind of special treatment would be worthwhile. But we have not decided in favor of that extension *just yet*.
Therefore, the rule is: "all list navigation properties (those potentially returning more than one entity) will cause DevForce to fetch from the database the first time ... unless the EntityManager's DefaultQueryStrategy instructs otherwise ... or the EntityManager is disconnected."
--
YOU know that the second query is covered by the "get all" query. What can you do?
You could change the DefaultQueryStrategy to CacheOnly; when you want a query to go to the database, you state so explicitly on the query itself. Otherwise all queries - and all navigations - are satisfied locally. This is the approach I recommend for Silverlight applications because you want to keep your awareness of server trips very high and very explicit.
You could add your own "ProductSupplierMapsFromCache" property that did exactly what you want.
You can change the way the ProductSupplierMaps behaves. This is an advanced feature that few know about.
We generate navigation properties to behave in a "normal way" but you can change that. If you look inside the generated code for this property, you will see a reference to a static field "ProductSupplierMapsEntityProperty". This field is of type NavigationEntityProperty. You are free to change some of its properties.
During your setup phase, you could call something like this:
var strategy = new EntityReferenceStrategy(EntityReferenceLoadStrategy.DoNotLoad, MergeStrategy.PreserveChanges);
Product.ProductSupplierMapsEntityProperty.RelationLink.ToRole.ReferenceStrategy = strategy;
Henceforth, the Product.ProductSupplierMaps navigation property will always attempt to satisfy the request from the cache because you said "DoNotLoad".
I'm not sure I like this last approach because it is so unexpected; it's there for you if you like it.
---
p.s.: There are some other curiosities in your post. The one I want to comment about is the statement "generated code from our Model". I'm not sure who did the generating but it certainly wasn't DevForce. I've never seen code like this before.