2010-11-17 20 views
3

J'utilise Dane Morgridge's repository code en tant que parent de ma classe de référentiel. Dans la classe parente - EFRepository - il existe une méthode qui appelle la clause Where d'un ObjectSet en passant une méthode Func. En appelant ce code et en l'assignant à ma grille, le processus prend 4 minutes. Toutefois, si je code l'appel à l'ObjectSet de manière définitive, cela ne prend que trois secondes. Des idées pourquoi? Il semble que le compilateur gâche quelque chose.Pourquoi le codage en dur d'une expression de fonction accélère-t-il la requête de quatre minutes?

private void button1_Click(object sender, RoutedEventArgs e) 
    {       
     IQueryable<PRODDATA> testP = test.Repository.Find(w => w.PCUST == 49 && w.PDTTK == 20101030); 

     DateTime firstDate = System.DateTime.Now; 
//This is where it takes the most time when passing in the expression above. When the espression is hardcoded (see below) it speeds it up considerably. 
     radGridView1.ItemsSource = testP; 
     DateTime secondDate = System.DateTime.Now;         

    } 

public class EFRepository<T> : IRepository<T> where T : PRODDATA 
{ 
    public IUnitOfWork UnitOfWork { get; set; } 
    private IObjectSet<T> _objectset; 
    private IObjectSet<T> ObjectSet 
    { 
     get 
     { 
      if (_objectset == null) 
      { 
       _objectset = UnitOfWork.Context.CreateObjectSet<T>(); 
      } 
      return _objectset; 
     } 
    } 

    public virtual IQueryable<T> All() 
    { 
     return ObjectSet.AsQueryable(); 
    } 

    public IQueryable<T> Find(Func<T, bool> expression) 
    { 
//Hardcoding this only takes 2 seconds. 
     //return ObjectSet.Where(w => w.PCUST == 49 && w.PDTTK == 20101030).AsQueryable(); 

//passing expression takes 4 minutes. 
     return ObjectSet.Where(expression).AsQueryable(); 
    } 

    public void Add(T entity) 
    { 
     ObjectSet.AddObject(entity); 
    } 

    public void Delete(T entity) 
    { 
     ObjectSet.DeleteObject(entity); 
    } 

    public void Save() 
    { 
     UnitOfWork.Save(); 
    } 
} 

Répondre

3

Parce que Find prend un Func<T,bool> au lieu d'un Expression<Func<T,bool>>. Vraisemblablement, cette requête est envoyée à un moteur DB, car il fonctionne sur un IQueryable<T>. Mais si l'expression est passée en tant que délégué et non en tant qu'expression vraie, la couche LINQ-to-whatever-DB n'est pas capable d'inspecter l'expression et de la transformer en SQL. Cela se traduit par l'envoi de l'ensemble de données du serveur db vers le code C#, où l'expression "where" est ensuite appliquée dans le CLR au lieu de dans le DB.

Modifier la signature de Find de

public IQueryable<T> Find(Func<T, bool> expression) 

à

public IQueryable<T> Find(Expression<Func<T, bool>> expression) 

Ensuite, voir comment il fonctionne.

+0

Parfait. Vous êtes un génie et merci. J'apprécie particulièrement que vous disiez le comment/pourquoi. –

+0

Pas de problème! Heureux d'entendre la solution a fonctionné. – cdhowie