Почему жесткое кодирование выражения функции ускоряет запрос на четыре минуты?
Я использую код хранилища Дейна Моргриджа в качестве родителя для моего класса хранилища. В родительском классе -EFRepository- есть метод, который вызывает предложение Where объекта Object, передавая метод Func. После вызова этого кода, а затем присвоения его моей сетке, процесс занимает 4 минуты. Однако, если я жестко закодирую вызов ObjectSet's Where, это займет всего три секунды. Есть идеи почему? Похоже, компилятор все испортил.
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();
}
}
1 ответ
Так как Find
занимает Func<T,bool>
вместо Expression<Func<T,bool>>
, Предположительно, этот запрос отправляется в механизм БД, так как он работает на IQueryable<T>
, Но если выражение передается как делегат, а не как истинное выражение, слой LINQ-to-what-DB не сможет проверить выражение и превратить его в SQL. Это приводит к тому, что весь набор данных отправляется с сервера базы данных в код C#, где выражение "где" затем применяется в CLR, а не в DB.
Изменить подпись Find
от
public IQueryable<T> Find(Func<T, bool> expression)
в
public IQueryable<T> Find(Expression<Func<T, bool>> expression)
Тогда посмотрите, как это работает.