New Posts New Posts RSS Feed: Querying only the Cache
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Querying only the Cache

 Post Reply Post Reply
Author
kosgia View Drop Down
Newbie
Newbie
Avatar

Joined: 13-May-2010
Location: Greece
Posts: 13
Post Options Post Options   Quote kosgia Quote  Post ReplyReply Direct Link To This Post Topic: Querying only the Cache
    Posted: 29-Jun-2010 at 4:10pm
Hi,
i have the following case:
 
I have an object A witch references object B. So, A has a foreign key to B. I would like to preload all A objects in Cache and then execute a query to get a subtotal of A's referencing a particular B. Please confirm me if the following method i use is the recomended one.
 
I have preloaded all A objects in the Cashe by executing:
1) DomainModelEntityManager.DefaultManager.A.Execute();
I would like to query the cashe and get only some A objects that reference a specific B object.
So i write something like this:
2) DomainModelEntityManager.DefaultManager.A.Where(A.B.Id = MyId).With(QueryStrategy.CacheOnly).Execute();
This will return nothing as, if i understand correctly, it will search in Cashe for objects B with the specific Id but, since no object B's are loaded, it will fail.
if i rewrite 1) as:
1a) DomainModelEntityManager.DefaultManager.A.Include("B").Execute();
Everything works fine.
If i rewrite 2) as:
2a) DomainModelEntityManager.DefaultManager.A.Where(A.B_fk_Id= MyId).With(QueryStrategy.CacheOnly).Execute();
Everything works again fine. This time i use the genrated by the object mapper foreign key property in my query predicate and if i understand correctly no access to B property was required to test for B.Id == MyId equality.
 
So here are the possible combinations that work for me.
A) Preload B objects with A's
1a) DomainModelEntityManager.DefaultManager.A.Include("B").Execute();
2) DomainModelEntityManager.DefaultManager.A.Where(A.B.Id = MyId).With(QueryStrategy.CacheOnly).Execute();
B) Use the genrated by the object mapper foreign key property and and not have to preload B's.
1) DomainModelEntityManager.DefaultManager.A.Execute();
2a) DomainModelEntityManager.DefaultManager.A.Where(A.B_fk_Id= MyId).With(QueryStrategy.CacheOnly).Execute();
 
Finally i would like to ask why when i use the floowing method:
2b) DomainModelEntityManager.DefaultManager.A.Where(A.B_fk_Id= MyId).With(QueryStrategy.Normal).Execute();
i get this exception:
Something in this query is not supported by the Microsoft Entity Framework. Perhaps the query compares entities or non-primitive types.   For example, “Where(o => o == anOrder)” compares Order entities. Instead, please try “Where(o => o.Id == anOrder.Id)” which compares integer Id values.
 
I get this exception whenever i try to put in a Where clause a predicate containing a foreign key property and executing the query on the datasource.
 
Thanks in advance,
Kostas
Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jun-2010 at 2:34pm
Originally posted by kosgia

I have preloaded all A objects in the Cashe by executing:
1) DomainModelEntityManager.DefaultManager.A.Execute();

In Silverlight, all data retrieval via the server is asynchronous, so you will need to use ExecuteAsync() rather than Execute() to load the cache.

 
Originally posted by kosgia

I would like to query the cashe and get only some A objects that reference a specific B object.

So i write something like this:

2) DomainModelEntityManager.DefaultManager.A.Where(A.B.Id = MyId).With(QueryStrategy.CacheOnly).Execute();

This will return nothing as, if i understand correctly, it will search in Cashe for objects B with the specific Id but, since no object B's are loaded, it will fail.

That's true, but if you did have Bs in the cache, you should be able to get your A's much more easily by getting an instance of the desired B, and then referencing its B.As.

Henceforward, I'm going to use Employees and Territories in my examples instead of As and Bs, as it makes the syntax clearer (and because there actually is a many-to-many association between Employees and Territories in the NorthwindIB database that you can work with). So you would get the desired instance anEmployee of Employee; its collection of related Territories would be anEmployee.Territories.


Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jun-2010 at 3:03pm
Originally posted by kosgia

 
Finally i would like to ask why when i use the floowing method:
2b) DomainModelEntityManager.DefaultManager.A.Where(A.B_fk_Id= MyId).With(QueryStrategy.Normal).Execute();
i get this exception:
Something in this query is not supported by the Microsoft Entity Framework. Perhaps the query compares entities or non-primitive types.   For example, “Where(o => o == anOrder)” compares Order entities. Instead, please try “Where(o => o.Id == anOrder.Id)” which compares integer Id values.

The Entity Framework (.NET 3.5 version) doesn't like foreign keys and doesn't think they should even be exposed. (This is changed in EF 4.0.)

You can get what you need as
DomainModelEntityManager.DefaultManager.B.Where(b=> b.Id= 
MyId).SelectMany(b=>b.A);

or in Employee-Territory terms, as
DomainModelEntityManager.DefaultManager.Territories.Where(t=> t.Id= 
MyId).SelectMany(t=>t.Employees);

Back to Top
kosgia View Drop Down
Newbie
Newbie
Avatar

Joined: 13-May-2010
Location: Greece
Posts: 13
Post Options Post Options   Quote kosgia Quote  Post ReplyReply Direct Link To This Post Posted: 01-Jul-2010 at 3:04am
Greg, thanks for replying.
 
Indeed my initial post is not quite explanatory.
i keep telling to myself... Don't write in forums late at night!
 
So this is what i am trying to do.
I want to execute a query only in cash to get the orders for a specific Customer and Employee without having to preload Customers and Employees.
So i guess i could only write it as:
1) DomainModelEntityManager.DefaultManager.Orders.Where(o=> O.Customer_fk_Id == MyCustomerId && O.Emploeyy_fk_Id == MyEmployeeId).With(QueryStrategy.CacheOnly).Execute();
I would have to use foreign keys here as Customers and Employees don't exist in cache.
If no results are returned i would like then to search my database.
Of course now i have to rephrase the query to be accepted by The Entity Framework (.NET 3.5 version).
2) DomainModelEntityManager.DefaultManager.Orders.Where(o=> O.Customer.Id == MyCustomerId && O.Employee.Id == MyEmployeeId).With(QueryStrategy.Normal).Execute();
 
Is there any other way to accomplish the same effect and not have to write the same query twice, with and without the use of foreign keys?
 
Thank you,
Kostas
Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 06-Jul-2010 at 6:16pm
You could retrieve just the needed Employee and Customer before running the query for Orders. That failing, I'm afraid you're stuck, in EF 1.0, with your two forms of the query.
Back to Top
kosgia View Drop Down
Newbie
Newbie
Avatar

Joined: 13-May-2010
Location: Greece
Posts: 13
Post Options Post Options   Quote kosgia Quote  Post ReplyReply Direct Link To This Post Posted: 07-Jul-2010 at 12:11am
Thank you Greg, just wanted to confirm this.
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down