2009-12-03 5 views
5

Je sais au sujet de la méthode décrite ici:Requête LINQ compilée & DataLoadOptions ... avec une torsion!

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

... mais cela ne fonctionne pas pour ma situation que j'obtenir:

« Définition des options de charge n'est pas autorisé après les résultats ont été renvoyé d'une requête. "

J'utilise des scripts CodeSmith PLINQO pour générer des entités et le code de gestionnaire, et le code de gestionnaire ressemble à ceci:

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); 
    } 
} 

J'ai d'abord essayé laissant tomber DataLoadOptions statique dans la classe Searchmanager comme ceci:

public static readonly DataLoadOptions MyOptions = 
    (new Func<DataLoadOptions>(() => 
    { 
     var option = new DataLoadOptions(); 
     option.LoadWith<Search>(x => x.Rule); 
     return option; 
    }))(); 

... puis en fournissant au contexte dans la méthode GetAll comme:

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

... et cela m'a donné l'erreur que j'ai noté ci-dessus. Est-ce parce que la requête est déjà compilée et que vous ne pouvez donc pas ajouter "Extra" DataLoadOptions? Si oui, comment serait-il possible d'appliquer les DataLoadOptions avant la compilation de la requête?

+0

vérifier la réponse affichée et faire accepter si vous avez l'info que vous voulez –

Répondre

0

Le message d'erreur vous indique exactement ce qui ne va pas. Vous ne pouvez pas appliquer DataLoadOptions après qu'une requête Linq a renvoyé des résultats. Ou, peut-être une meilleure façon de dire ceci est la suivante. Si vous souhaitez appliquer DataLoadOptions, faites-le avant d'exécuter la requête. Vous ne pouvez pas le faire par la suite.

+0

En fait, l'erreur se produit avant que la requête est appelée, comme le montre: publique IQueryable GetAll() { Context.LoadOptions = MyOptions; return Query.GetAll (Contexte); } – krisg

0

Vous ne pouvez définir les options de chargement qu'une seule fois pour une requête compilée. L'erreur doit être levée lors du second appel. Déplacez l'affectation vers un constructeur statique et cela devrait résoudre votre problème.

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

Cette affectation est trop tardive si le contexte a déjà renvoyé des résultats de requête. Cela n'a rien à voir avec les requêtes compilées et tout ce qui concerne l'affectation de la propriété LoadOptions de DataContext. Malheureusement, ce comportement de la propriété LoadOptions n'est pas documenté sur msdn.

2

Dans la propriété setter de la classe DataContext, une condition vérifie si le DataContext possède des objets dans son cache, et que LoadOptions n'est pas NULL, et que l'instance LoadOptions que vous essayez de définir n'est pas la même que celui déjà défini, alors vous obtenez cette exception.

Variante 1. Créer un nouveau contexte pour chaque requête (probablement pas une bonne idée)
Alternative # 2. Appelez la méthode ClearCache à l'aide de la réflexion, puis créez une nouvelle méthode LoadOptions de manière statique, assignez-la au contexte, puis enfin, obtenez la requête compilée.

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; 
    } 
} 
Questions connexes