views:

506

answers:

1

Consider this compiled linq-to-sql query:

private static Func<LINQDBDataContext, string, IQueryable<Pet>> 
    QueryFindByName =
    CompiledQuery.Compile((
    MyLinqDataContext context, string name) =>
    from p in context.Pets where p.Name == name select p);

But I'm holding a private reference to context in the class already and I want to be able to mark the query as public without exposing the context e.g.

private static MyLinqDataContext context = SomeUtilityClass.GetMeMyContext();
//...
public static Func<string, IQueryable<Pet>> QueryFindByName = 
    CompiledQuery.Compile((string name) =>
    from p in this.context.Pets where p.Name == name select p); 
    //doesn't compile as expects TArg0 to be a DataContext.

Is there any way to do this without creating a public wrapper function for each query??

+2  A: 

Is your reference to the context static, i.e. you've got a single context across the type? That doesn't sound like a great idea to me. Anyway, leaving that to one side, you can do:

// Private version which takes a context...
private static Func<LINQDBDataContext, string, IQueryable<Pet>> 
    QueryFindByNameImpl =
    CompiledQuery.Compile((
    LINQDBDataContext context, string name) =>
    from p in context.Pets where p.Name == name select p);

// Public version which calls the private one, passing in the known context
public static Func<string, IQueryable<Pet>> QueryFindByName = 
    name => QueryFindByNameImpl(contextFromType, name);

EDIT: Okay, if you don't like this approach, you could try writing your own generic wrappers around CompiledQuery.Compile instead. For example:

public static class LinqHelpers
{
    public static Func<TArg0, TResult> Compile<TContext, TArg0, TResult>
        (this TContext context, 
         Expression<Func<TContext, TArg0, TResult>> query)
        where TContext : DataContext
    {
        Func<TContext, TArg0, TResult> compiled = 
            CompiledQuery.Compile(query);
        return arg => compiled(context, arg);
    }
}

(And so on for more parameters.)

I haven't tried even compiling that, but I think it will work. You'd then use it like this:

private static MyLinqDataContext context = SomeUtilityClass.GetMeMyContext();

public static Func<string, IQueryable<Pet>> QueryFindByName = context.Compile
    ((LINQDBDataContext context, string name) =>
      from p in context.Pets where p.Name == name select p);

It's still creating a wrapper of course, but at least you only need to do it in one place. If your objection to creating wrappers was anything other than the tedium/code mess of it, please give more details.

Jon Skeet
Cheers, but that's creating a wrapper function which is what I'm trying to avoid.
ctrlalt3nd
Thanks. I'm just playing around and thought it might be a useful technique. But it's suprisingly hard to achieve ;)
ctrlalt3nd