471,330 Members | 1,634 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,330 software developers and data experts.

Cache in Dlinq

I need to repeatedly execute same queries which returns single entity by id,
like:

Customer cust = (from c in db.Customers
where c.CustomerID=="AIRBU"
select c).SingleOrDefault();

DLinq holds tracked object list internally so customer "AIRBU" exists in
memory.

How to force DLinq to look its list and not to make round trip to server ?
I looked into Entity Framework also but havent found any caching solution in
EF.

Andrus.
Jun 27 '08 #1
19 1437
"LINQ in Action" states that Single() is an exception, in that it
checks the cache first, not the database. I haven't tried it yet (long
day...) - but worth a try ;-p

(I'm assuming that SingleOrDefault doesn't qualify for this exception
since you've tried it... - and it would presumably need the predicate
to be based solely on the primary key column[s])

Marc
Jun 27 '08 #2
OK; I couldn't find a single case when Single() did anything other
than hit the database... I wonder what the authors had in mind?

Anyways... here is something truly, truly hacky that does the job; I'm
off to lather...
using System;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using WindowsFormsApplication4; // ns to DataClasses1DataContext =
Northwind

static class DataContextExt {
public static T GetFromCache<T>(this Table<Ttable, params
object[] keyValues) where T : class
{
if (table == null) throw new ArgumentNullException("table");
return GetFromCache<T>(table.Context, keyValues);
}
public static T GetFromCache<T>(this DataContext context, params
object[] keyValues) where T : class
{
// surfactants on standby - this is dirty, plain and simple
// (oh, and brittle, and not compile-time safe, and requires
// sufficient trust... you get the idea; nasty nasty nasty)
if (context == null) throw new
ArgumentNullException("context");
const BindingFlags FLAGS = BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic;
object services = context.GetType().GetProperty("Services",
FLAGS).GetValue(context, null);

object[] args = { context.Mapping.GetMetaType(typeof(T)),
keyValues };
Type[] paramTypes = { typeof(MetaType), typeof(object[]) };
return (T)services.GetType().GetMethod("GetCachedObject",
FLAGS, null, paramTypes, null).Invoke(services, args);
}
}
static class Program
{
static void Main()
{
using (DataClasses1DataContext ctx = new
DataClasses1DataContext())
{
// cache the original
Supplier sup = ctx.Suppliers.First();
int id = sup.SupplierID;

// get from the context
Supplier same = ctx.GetFromCache<Supplier>(id);
Trace.WriteLine(ReferenceEquals(sup, same), "Got from
Context");

// get from the table
Supplier again = ctx.Suppliers.GetFromCache(id);
Trace.WriteLine(ReferenceEquals(sup, again), "Got from
Table");

// and check what happens if it isn't there...
Supplier nothing = ctx.GetFromCache<Supplier>(53);
Trace.WriteLine(ReferenceEquals(nothing, null), "Null when
missing");
}

}
}
Jun 27 '08 #3
Marc,
OK; I couldn't find a single case when Single() did anything other
than hit the database... I wonder what the authors had in mind?
MSDN clearly states that every simple query must return result form identity
cache if it exists, not reaching to database.

Do you have any idea why it is not working ?
How to use identity cache in documented way ?
Anyways... here is something truly, truly hacky that does the job; I'm
off to lather...
Where did you found information which allows to create such program ?
I havent found any documentation on Services property and GetCachedObject
method.

Andrus.
Jun 27 '08 #4
MSDN clearly states that every simple query must return result form identity
cache if it exists, not reaching to database.
Can you cite a source there?
Do you have any idea why it is not working ?
How to use identity cache in documented way ?
I have asked that very question on a LINQ group; no answer yet...
Where did you found information which allows to create such program ?
From grubbling around... it is dirty and brittle (i.e. it will break if
somebody [quite reasonably] refactors the internal implementation)...

Marc
Jun 27 '08 #5
MSDN clearly states that every simple query must return result form identity
cache if it exists, not reaching to database.
(in particular - yes it should return the same instance from the cache
[and it does] - the question is focused around whether it hits the db...
can you cite a page for the above claim?)
Jun 27 '08 #6
>MSDN clearly states that every simple query must return result form
>identity cache if it exists, not reaching to database.

(in particular - yes it should return the same instance from the cache
[and it does] - the question is focused around whether it hits the db...
can you cite a page for the above claim?)
http://msdn2.microsoft.com/en-us/library/bb399376.aspx

Quote:
If the object requested by the query is easily identifiable as one already
retrieved, no query is executed. The identity table acts as a cache of all
previously retrieved objects.

Andrus.
Jun 27 '08 #7
So I guess it comes down to defining "easily identifiable"... I'll run
some more tests at some point (not "right now"), but I don't know how
easy / hard it will be to get working... which is why I am trying to get
some input from the LINQ people...

Marc
Jun 27 '08 #8
Marc,
So I guess it comes down to defining "easily identifiable"... I'll run
some more tests at some point (not "right now"), but I don't know how easy
/ hard it will be to get working... which is why I am trying to get some
input from the LINQ people...
id == constant expression if definitely "easily identifiable".
So it seems that we have found serious bug in Linq-SQL.
Can we submit product feedback to Microsoft?
Is it reasonable to subclass DataContext to fix this ?

There is also bug in "Linq in Action" book if it states that cache works
only with Single(). Ca we inform author about this ?

Andrus.
Jun 27 '08 #9
Can we submit product feedback to Microsoft?
Feel free ["connect", or the managed LINQ forum]; personally I'd like
to do a little more looking first...
Is it reasonable to subclass DataContext to fix this ?
The cache is internal, not protected. Subclassing won't help.
Ca we inform author about this ?
Authors plural; but I guess I can try to find some e-mail addresses
and see what they say...

Marc
Jun 27 '08 #10
For info, looked at the EF offering... unfortunately it is harder to
profile, and I don't have my SQL profiler handy; following gets the
right objects at least - but I don't know (until I get a few seconds
to switch servers) how many times it hits the database:

using System;
using System.Data;
using System.Data.Objects.DataClasses;
using System.Linq;
using AdventureWorksModel;

static class Program
{
[STAThread]
static void Main()
{
AdventureWorksEntities1 ctx = new AdventureWorksEntities1();

string setName = GetEntitySetName<Customer>(false),
qualifiedSetName = GetEntitySetName<Customer>(true),
keyName = GetKeyName<Customer>();

// expect DB hit here
var cust = ctx.Customer.First();
var id = cust.CustomerID;

// look by known key
EntityKey key = ctx.GetEntityKey(setName, cust);
var byKey = ctx.GetObjectByKey(key);
object obj;
if (ctx.TryGetObjectByKey(key, out obj))
{
var cust1 = (Customer)obj;
Console.WriteLine("Got...");
}

// look by custom key and a new ctx (assume a single primary
key for keyName)
AdventureWorksEntities1 ctx2 = new AdventureWorksEntities1();
EntityKey customKey = new EntityKey(qualifiedSetName, keyName,
id);
// (different instance, but it works...; expect another DB hit
here)
var cust2 = ctx2.GetObjectByKey(customKey);

// look using predicates
var cust3 = ctx.Customer.Where(x =x.CustomerID ==
id).First();
var cust4 = ctx.Customer.First(x =x.CustomerID == id);
}

static string GetEntitySetName<T>(bool qualified) where T :
EntityObject
{
EdmEntityTypeAttribute attrib =
(EdmEntityTypeAttribute)Attribute.GetCustomAttribu te(typeof(T),
typeof(EdmEntityTypeAttribute));
if (attrib == null) return null;
return qualified ? (attrib.NamespaceName + "." +
attrib.Name) : attrib.Name;
}
static string GetKeyName<T>() where T : EntityObject
{
return ( from prop in typeof(T).GetProperties()
let attrib = (EdmScalarPropertyAttribute)
Attribute.GetCustomAttribute(prop,
typeof(EdmScalarPropertyAttribute))
where attrib != null && attrib.EntityKeyProperty
select prop.Name).Single();
}
}
Jun 27 '08 #11
Marc,
For info, looked at the EF offering... unfortunately it is harder to
profile, and I don't have my SQL profiler handy; following gets the
right objects at least - but I don't know (until I get a few seconds
to switch servers) how many times it hits the database:
Thank you. Have you got any idea why Linq-SQL does not use cache ?

Andrus.
Jun 27 '08 #12
No; I've been invited to log a "connect" bug about it - I just want to
make sure I can't get it to work first...

Marc
Jun 27 '08 #13

Marc,
Logged:
https://connect.microsoft.com/Visual...dbackID=340036
Thank you.
I marked it as very important.

Andrus.
Jun 27 '08 #15

Marc,
Logged:
https://connect.microsoft.com/Visual...dbackID=340036
Thank you.
I marked it as very important.

Andrus.

Jun 27 '08 #16
On Apr 23, 4:38*pm, Marc Gravell <marc.grav...@gmail.comwrote:
Can we submit product feedback to Microsoft?

Feel free ["connect", or the managed LINQ forum]; personally I'd like
to do a little more looking first...
Is it reasonable to subclass DataContext to fix this ?

The cache is internal, not protected. Subclassing won't help.
Ca we inform author about this ?

Authors plural; but I guess I can try to find some e-mail addresses
and see what they say...

Marc
Andrus, thanks for letting us know about this issue. I suspect the
confusion stems from a change between the betas and the final RTM of
LINQ to SQL. I'm trying to get confirmation from the product teams and
will let you know if we find otherwise. If you find other issues with
the LINQ in Action book, feel free to let us know in our forum at
http://www.manning-sandbox.com/forum.jspa?forumID=302. Also, we do
have an errata list at http://linqinaction.net/blogs/main/p...on-errata.aspx
which we will update once we receive confirmation on this issue.

Jim Wooley
www.ThinqLinq.Com
www.LinqInAction.net
Jun 27 '08 #17
Now that is service with a smile! Anything you can find out would be
appreciated...

Loving the book, btw.

Marc
Jun 27 '08 #18
Marc,
Logged:
https://connect.microsoft.com/Visual...dbackID=340036
Microsoft has marked this issue as Closed (Fixed) without providing any
information.

What do you think about this behaviour ?

Do you have any more information about this issue ?

Andrus.

Jun 27 '08 #19
Do you have any more information about this issue ?

My response is already on connect (from ages ago). I know nothing more.
Jun 27 '08 #20

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

6 posts views Thread by Lei Jiang | last post: by
7 posts views Thread by Senna | last post: by
3 posts views Thread by Chiranjib | last post: by
reply views Thread by Scott Nonnenberg [MSFT] | last post: by
reply views Thread by Scott Nonnenberg [MSFT] | last post: by
reply views Thread by Scott Nonnenberg [MSFT] | last post: by
4 posts views Thread by Brett Romero | last post: by
1 post views Thread by Andrus | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.