2009-12-03 19 views
5

私はここで説明する方法を知っている:コンパイル済みLINQクエリとDataLoadOptions ...

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

...しかし、私は得ると、これは私の状況では動作しません。結果は持って後にロードオプションを設定

が」許可されていませんクエリから返されました。

は、私は、エンティティとマネージャーのコードを生成するためにCodesmith PLINQOスクリプトを使用しています、とマネージャーのコードは次のようになります。

:私が最初にこのようなSearchmanagerクラスに静的DataLoadOptionsをドロップしようとした

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をどのように適用することができますか?

+0

が投稿答えをチェックし、あなたが欲しい情報 –

答えて

0

エラーメッセージ自体は、何が間違っているかを正確に示しています。 Linqクエリが結果を返した後でDataLoadOptionsを適用することはできません。あるいは、これを言う良い方法は次のとおりです。 DataLoadOptionsを適用する場合は、クエリを実行する前に行います。後でそれをすることはできません。

+0

示すようにクエリが呼び出される前に、実際にエラーが発生しました場合にそれを受け入れませんMyOptions; return Query.GetAll(コンテキスト); } – krisg

0

コンパイルされたクエリに対してのみ、ロードオプションを1回設定することができます。 2番目の呼び出しでエラーがスローされる必要があります。代入を静的コンストラクタに移動すると、問題が解決されます。

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を作成し、それをコンテキストに割り当て、最後にコンパイルされたクエリを取得します。 = 公共のIQueryable GETALL() { Context.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; 
    } 
} 
関連する問題