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<T> table, 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");
}
}
}