C# 已编译的LINQ查询和数据加载选项。。。转一转!

C# 已编译的LINQ查询和数据加载选项。。。转一转!,c#,linq,compiled-query,loadoptions,C#,Linq,Compiled Query,Loadoptions,我知道这里讨论的方法: 。。。但这不适合我的情况,因为我得到了: 从查询返回结果后,不允许设置加载选项 我正在使用Codesmith PLINQO脚本生成实体和管理器代码,管理器代码如下所示: public partial class SearchManager { #region Query // A private class for lazy loading static compiled queries. private static partial

我知道这里讨论的方法:

。。。但这不适合我的情况,因为我得到了:

从查询返回结果后,不允许设置加载选项

我正在使用Codesmith PLINQO脚本生成实体和管理器代码,管理器代码如下所示:

public partial class SearchManager
{       
    #region Query
    // A private class for lazy loading static compiled queries.
    private static partial class Query
    {
        internal static readonly Func<MyDataContext,IOrderedQueryable<Search>> 
            GetAll = CompiledQuery.Compile(
                (MyDataContext db) =>
                from s in db.Search
                orderby s.Name
                select s);
    } 
    #endregion


    public IQueryable<Search> GetAll()
    {
        return Query.GetAll(Context);
    }
}
public static readonly DataLoadOptions MyOptions = 
    (new Func<DataLoadOptions>(() =>
    {
        var option = new DataLoadOptions();
        option.LoadWith<Search>(x => x.Rule);
        return option;
    }))();
我首先尝试将静态DataLoadOptions放入Searchmanager类,如下所示:

public partial class SearchManager
{       
    #region Query
    // A private class for lazy loading static compiled queries.
    private static partial class Query
    {
        internal static readonly Func<MyDataContext,IOrderedQueryable<Search>> 
            GetAll = CompiledQuery.Compile(
                (MyDataContext db) =>
                from s in db.Search
                orderby s.Name
                select s);
    } 
    #endregion


    public IQueryable<Search> GetAll()
    {
        return Query.GetAll(Context);
    }
}
public static readonly DataLoadOptions MyOptions = 
    (new Func<DataLoadOptions>(() =>
    {
        var option = new DataLoadOptions();
        option.LoadWith<Search>(x => x.Rule);
        return option;
    }))();
。。。然后在GetAll方法中将其提供给上下文,如下所示:

public IQueryable<Search> GetAll()
{
    Context.LoadOptions = MyOptions;
    return Query.GetAll(Context);
}

…这给了我上面提到的错误。这是因为查询已编译,因此无法添加额外的DataLoadOptions吗?如果是这样,在编译查询之前如何应用DataLoadOptions?

错误消息本身会准确地告诉您错误所在。Linq查询返回结果后,无法应用DataLoadOptions。或者,也许更好的说法如下。如果要应用DataLoadOptions,请在执行查询之前应用。以后不能这样做。

对于已编译的查询,只能设置一次加载选项。必须在第二次调用时抛出错误。将赋值移到一个静态构造函数,这样应该可以解决您的问题

public IQueryable<Search> GetAll() {
     Context.LoadOptions = MyOptions;
     return Query.GetAll(Context);
 } 

如果上下文已返回任何查询结果,则此分配太迟。这与已编译的查询无关,与分配DataContext的LoadOptions属性有关。不幸的是,LoadOptions属性的这种行为没有记录在msdn上。

在DataContext类的setter属性中,有一个条件检查DataContext的缓存中是否有任何对象,LoadOptions不为null,并且您尝试设置的LoadOptions实例与已设置的实例不同,然后你会得到这个例外

备选案文1。为每个查询创建一个新的上下文可能不是一个好主意 备选案文2。使用反射调用ClearCache方法,然后静态地创建一个新的LoadOptions,将其分配给上下文,最后获取已编译的查询

public partial class SearchManager
{       
    #region Query
    // A private class for lazy loading static compiled queries.
    private static partial class Query
    {
        internal static readonly Func<MyDataContext,IOrderedQueryable<Search>> GetAll 
        {
            get {
                return CompiledQuery.Compile(
                    (MyDataContext db) =>
                        from s in db.Search
                        orderby s.Name
                        select s);
            }
        } 
    #endregion

    public IQueryable<Search> GetAll()
    {
        Context.ClearCache();
        Context.LoadOptions = MyOptions;
        return Query.GetAll(Context);
    }

    public static readonly DataLoadOptions MyOptions = 
        (new Func<DataLoadOptions>(() => MakeLoadOptions<Search>(x=>x.Rule)))();
}

public static class Extensions {
    public static void ClearCache(this DataContext context)
    {
        const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
        var method = context.GetType().GetMethod("ClearCache", FLAGS);
        method.Invoke(context, null);
    }

    public static DataLoadOptions MakeLoadOptions<TEntity, TResult>(this Expression<Func<TEntity,TResult>> func) {
        DataLoadOptions options = new DataLoadOptions();
        options.LoadWith(func);
        return options;
    }
}

实际上,错误发生在调用查询之前,如图所示:public IQueryable GetAll{Context.LoadOptions=MyOptions;return query.GetAllContext;}检查发布的答案,如果您得到了所需的信息,请接受它