代码之家  ›  专栏  ›  技术社区  ›  krisg

编译的linq查询和dataloadoptions…一个扭曲!

  •  6
  • krisg  · 技术社区  · 15 年前

    我知道这里讨论的方法:

    Solving common problems with Compiled Queries in Linq to Sql for high demand ASP.NET websites

    …但这不适合我的情况,因为我得到一个:

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

    我正在使用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 回复  |  直到 15 年前
        1
  •  2
  •   Marcel Valdez Orozco    13 年前

    在datacontext类的setter属性中,有一个条件检查datacontext的缓存中是否有任何对象,并且loadoptions不为空,并且您试图设置的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;
        }
    }
    
        2
  •  0
  •   Randy Minder    15 年前

    错误消息本身告诉您到底是什么问题。在linq查询返回结果后,不能应用dataloadoptions。或者,也许更好的说法如下。如果要应用dataloadoptions,请在执行查询之前应用。你以后不能这样做。

        3
  •  0
  •   Bryce Kahle    14 年前

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

        4
  •  0
  •   Amy B    14 年前
    public IQueryable<Search> GetAll() {
         Context.LoadOptions = MyOptions;
         return Query.GetAll(Context);
     } 
    

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