Linq编译查询而不传递上下文

时间:2009-02-18 16:35:51

标签: c# linq linq-to-sql precompiled

考虑这个编译的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 个答案:

答案 0 :(得分:3)

您对上下文的引用是否是静态的,即您在该类型中有一个单独的上下文?这对我来说听起来不是一个好主意。无论如何,把它留在一边,你可以做到:

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

当然,它仍在创建一个包装器,但至少你只需要在一个地方完成它。如果您对创建包装器的反对意见不是单调乏味/代码混乱,请提供更多详细信息。