2009-12-03 11 views
5

Conosco il metodo discusso qui:query LINQ compilata e DataLoadOptions ... con una svolta!

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

... ma questo non funziona per la mia situazione come ho ottenere un:

"Impostazione delle opzioni di caricamento non è consentito dopo i risultati hanno stato restituito da una query. "

Sto usando gli script Codesmith PLINQO per generare entità e il codice manager, e il codice manager guarda qualcosa di simile:

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

prima ho provato cadere un DataLoadOptions statici nella classe Searchmanager in questo modo:

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

... poi fornire al contesto nel metodo GetAll come:

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

... e questo mi ha dato l'errore che ho notato sopra. È perché la query è già stata compilata e quindi non è possibile aggiungere "extra" a DataLoadOptions? In tal caso, come sarebbe possibile applicare le DataLoadOptions prima che la query fosse compilata?

+0

controllo la risposta distaccato e farlo accettare se hai le informazioni che desidera –

risposta

0

Il messaggio di errore indica esattamente ciò che è sbagliato. Non è possibile applicare DataLoadOptions dopo che una query di Linq ha restituito risultati. O forse un modo migliore per dire questo è il seguente. Se si desidera applicare DataLoadOptions, farlo prima di eseguire la query. Non puoi farlo dopo.

+0

In realtà l'errore si verifica prima che la query è chiamato, come mostrato: pubblico IQueryable GetAll() { Context.LoadOptions = MyOptions; return Query.GetAll (Context); } – krisg

0

È possibile impostare le opzioni di caricamento solo una volta per una query compilata. L'errore deve essere generato durante la seconda chiamata. Sposta il compito a un costruttore statico e questo dovrebbe risolvere il tuo problema.

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

Questo compito è troppo tardi, se il contesto ha già restituito risultati di query. Questo non ha nulla a che fare con le query compilate e tutto ciò che riguarda l'assegnazione della proprietà LoadOptions di DataContext. Sfortunatamente, questo comportamento della proprietà LoadOptions non è documentato su msdn.

2

Nella proprietà setter della classe DataContext, esiste una condizione che controlla se DataContext ha oggetti nella sua cache e LoadOptions NON è null e l'istanza LoadOptions che si sta tentando di impostare non è uguale a quello già impostato, quindi ottieni questa eccezione.

Alternativa n. 1. Creare un nuovo contesto per ogni query (probabilmente non è una buona idea)
Alternativa n. 2. Chiama il metodo ClearCache usando reflection, quindi crea staticamente un nuovo LoadOptions, assegnalo al Context, infine ottieni la query compilata.

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