2009-12-03 17 views
5

我知道這裏討論的方法:編譯LINQ查詢和DataLoadOptions ...有一個轉折!

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?

+0

檢查公佈答案,確實接受它,如果你得到了你想要 – 2011-10-17 07:44:53

回答

0

錯誤消息本身告訴你到底什麼是錯的。在Linq查詢返回結果後,您無法應用DataLoadOptions。或者,也許有更好的方式來說這個如下。如果您想要應用DataLoadOptions,請在執行查詢之前執行此操作。事後你不能這樣做。

+0

實際發生錯誤的查詢調用之前的信息,如圖所示: 公衆的IQueryable GETALL(){ Context.LoadOptions = MyOptions; return Query.GetAll(Context); } – krisg 2009-12-04 00:46:30

0

您只能爲編譯查詢設置一次加載選項。錯誤必須在第二次調用中引發。將任務移到一個靜態構造函數中,這應該可以解決您的問題。

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

如果上下文已經返回任何查詢結果,則此分配爲時已晚。這與編譯查詢無關,並且與分配DataContext的LoadOptions屬性有關。不幸的是,這個LoadOptions屬性的行爲沒有記錄在msdn上。

2

在DataContext類的setter屬性中,存在一個條件,用於檢查DataContext是否在其Cache中包含任何對象,並且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; 
    } 
}