Почему жесткое кодирование выражения функции ускоряет запрос на четыре минуты? - PullRequest
3 голосов
/ 17 ноября 2010

Я использую код хранилища Дейна Моргриджа в качестве родителя для моего класса хранилища.В родительском классе - 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 Ответ

3 голосов
/ 17 ноября 2010

Потому что 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)

Тогда посмотрите, как это работает.

...