6

我知道这里讨论的方法:

解决高需求 ASP.NET 网站的 Linq to Sql 中编译查询的常见问题

...但这不适用于我的情况,因为我得到了:

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

我正在使用 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);
    }
}

我首先尝试将静态 DataLoadOptions 放入 Searchmanager 类中,如下所示:

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?

4

4 回答 4

2

在DataContext类的setter属性中,有一个条件是检查DataContext的Cache中是否有任何对象,并且LoadOptions不为空,并且你尝试设置的LoadOptions实例与已经设置的不一样,然后你得到那个例外。

备选方案#1。为每个查询创建一个新的上下文(可能不是一个好主意)
替代#2。使用反射调用ClearCache方法,然后静态新建一个LoadOptions,赋值给Context,最后得到编译好的查询。

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;
    }
}
于 2012-03-05T09:22:03.870 回答
0
public IQueryable<Search> GetAll() {
     Context.LoadOptions = MyOptions;
     return Query.GetAll(Context);
 } 

如果 Context 已经返回了任何查询结果,那么这个分配就太晚了。这与编译查询无关,与分配 DataContext 的 LoadOptions 属性有关。不幸的是,msdn 上没有记录 LoadOptions 属性的这种行为。

于 2011-05-24T17:14:08.060 回答
0

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

于 2010-07-27T14:14:57.323 回答
0

错误消息本身会告诉您究竟出了什么问题。在 Linq 查询返回结果后,您无法应用 DataLoadOptions。或者,也许更好的说法如下。如果要应用 DataLoadOptions,请在执行查询之前执行此操作。之后你不能这样做。

于 2009-12-03T12:32:13.597 回答