2009-12-03 7 views
5

Ich weiß um die Methode, die hier besprochen:Kompilierte LINQ-Abfrage und DataLoadOptions ... mit einem Twist!

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

... aber für meine Situation nicht arbeiten, wie ich eine bekommen:

„Optionen Lesen Einstellung wird nicht nach den Ergebnissen erlaubt hat wurde von einer Abfrage zurückgegeben. "

Ich bin mit Codesmith PLINQO Skripte Einheiten und Manager-Code zu generieren, und der Manager-Code sieht etwa so aus:

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

Ich versuchte zunächst, eine statische Dataload in die Search Klasse wie folgt fallen:

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

... vorausgesetzt, es dann auf den Kontext, in dem GetAll Verfahren wie:

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

... und das gab mir den oben erwähnten Fehler. Liegt das daran, dass die Abfrage bereits kompiliert wurde und daher nicht "extra" DataLoadOptions hinzugefügt werden kann? Wenn ja, wie wäre es möglich, DataLoadOptions vor der Kompilierung der Abfrage anzuwenden?

+0

Kontrolle der entsandte Antwort und tun es akzeptieren, wenn Sie die Informationen, die Sie –

Antwort

0

Die Fehlermeldung selbst sagt Ihnen genau, was falsch ist. Sie können DataLoadOptions nicht anwenden, nachdem eine Linq-Abfrage Ergebnisse zurückgegeben hat. Oder, vielleicht ist ein besserer Weg, dies zu sagen, wie folgt. Wenn Sie DataLoadOptions anwenden möchten, tun Sie dies, bevor Sie die Abfrage ausführen. Das kannst du danach nicht tun.

+0

auftritt Eigentlich wollen bekam die Fehler, bevor die Abfrage aufgerufen wird, wie gezeigt: public IQueryable GetAll() { Context.LoadOptions = MeineOptions; Rückgabe Query.GetAll (Kontext); } – krisg

0

Sie können die Ladeoptionen nur einmal für eine kompilierte Abfrage festlegen. Der Fehler muss beim zweiten Aufruf ausgelöst werden. Verschieben Sie die Zuweisung in einen statischen Konstruktor, und das sollte Ihr Problem lösen.

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

Diese Zuordnung ist zu spät, wenn der Kontext bereits Abfrageergebnisse zurückgegeben hat. Dies hat nichts mit kompilierten Abfragen und allem, was mit der Zuweisung der LoadOptions-Eigenschaft von DataContext zu tun hat, zu tun. Leider ist dieses Verhalten der LoadOptions-Eigenschaft in msdn nicht dokumentiert.

2

In der Setter-Eigenschaft der DataContext-Klasse gibt es eine Bedingung, die überprüft, ob der DataContext Objekte in seinem Cache hat und die LoadOptions NICHT NULL ist und die LoadOptions-Instanz, die Sie einstellen möchten, nicht dieselbe ist der eine schon gesetzt, dann bekommst du diese Ausnahme.

Alternative # 1. Erstellen Sie einen neuen Kontext für jede Abfrage (wahrscheinlich keine gute Idee)
Alternative # 2. Rufen Sie die ClearCache-Methode mit Reflection auf, erstellen Sie dann eine neue LoadOptions-Datei statisch, weisen Sie sie dem Kontext zu und rufen Sie abschließend die kompilierte Abfrage ab.

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