Linq скомпилировал запросы без передачи контекста

Рассмотрим этот скомпилированный запрос linq-to-sql:

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);

Но у меня уже есть частная ссылка на контекст в классе, и я хочу иметь возможность пометить запрос как общедоступный, не раскрывая контекст, например.

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.

Есть ли способ сделать это без создания общедоступной функции-оболочки для каждого запроса??


person ctrlalt3nd    schedule 18.02.2009    source источник


Ответы (1)


Является ли ваша ссылка на контекст статической, т.е. у вас есть один контекст для всего типа? Мне это не кажется хорошей идеей. В любом случае, оставив это в стороне, вы можете сделать:

// 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);

РЕДАКТИРОВАТЬ: Хорошо, если вам не нравится этот подход, вы можете вместо этого попробовать написать свои собственные общие оболочки вокруг CompiledQuery.Compile. Например:

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);
    }
}

(И так далее для других параметров.)

Я даже не пытался это компилировать, но думаю, это сработает. Затем вы использовали бы его следующим образом:

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);

Конечно, это все еще создание оболочки, но, по крайней мере, вам нужно сделать это только в одном месте. Если ваше возражение против создания оберток было чем-то иным, кроме утомительной работы/беспорядка в коде, пожалуйста, дайте более подробную информацию.

person Jon Skeet    schedule 18.02.2009
comment
Ура, но это создает функцию-оболочку, чего я пытаюсь избежать. - person ctrlalt3nd; 18.02.2009
comment
Спасибо. Я просто играю и подумал, что это может быть полезной техникой. Но добиться этого на удивление сложно ;) - person ctrlalt3nd; 18.02.2009