Linq скомпилировал запросы без передачи контекста - PullRequest
4 голосов
/ 18 февраля 2009

Рассмотрим этот скомпилированный запрос 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.

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

1 Ответ

3 голосов
/ 18 февраля 2009

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

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

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

...