Entity Framework DbSet <TEntity>. Где (e => true) производительность - PullRequest
0 голосов
/ 05 марта 2019

Я использую Entity Framework 6 для доступа к базе данных.

Есть ли разница в производительности между следующими двумя методами?

public IEnumerable<TEntity> GetAll()
{
    using (var context = new DbContext())
        return context.Set<TEntity>().ToList();
}

и

public IEnumerable<TEntity> GetAll()
{
    using (var context = new DbContext())
        return context.Set<TEntity>().Where(e => true).ToList();
}

Я спрашиваю, потому что я хотел бы использовать условные предикаты.Примерно так:

public IEnumerable<TEntity> GetAll(TKey fKey)
{
    using (var context = new DbContext())
        return context.Set<TEntity>()
                      .Where(e => fKey != null ? e.fKey == fKey : true).ToList();
}

, где fKey будет внешним ключом.

Обновление : так как многие комментарии сосредоточены на моем последнем примере, ясогласен, это неправильный вариант использования, я объясню, почему я спрашиваю.

Итак, у меня есть метод репозитория, который выглядит примерно так:

public class EntityRepository
{
    public IEnumerable<Entity> GetAll(Expression<Func<Entity, bool>> predicate)
    {
        using (var context = new DbContext())
            return context.Set<Entity>.Where(predicate).ToList();
    }
}

И я использую этот метод изМетод действия контроллера Web API.Примерно так:

public IHttpActionResult GetEntities(string param1, string param2, string param3)
{
    Expression<Func<Entity, bool>> predicate = e =>
         (param1 != null ? e.field1 == param1 : true)
         && (param2 != null ? e.field2 == param2 : true)
         && (param3 != null ? e.field3 == param3 : true);
    var entities = EntityRepository.GetAll(predicate);
    return Ok(entities);
}

Итак, здесь я получаю некоторые параметры запроса из URI и создаю предикат на их основе.Некоторые из этих параметров могут быть null, и в этом случае я не хочу фильтровать их.Но я не хочу создавать разные предикаты для всех комбинаций параметров, равных null s или нет.

Я знаю, что мог бы прочитать весь набор и отфильтровать один за другим впоследствии, ноэто заняло бы много памяти с большими наборами данных.

Итак, просто чтобы прояснить мой вопрос : Это правильный подход?Если все 3 параметра null (в этом случае будет возвращен весь набор), вызывает ли этот метод какие-либо потери производительности?

1 Ответ

0 голосов
/ 05 марта 2019

Я не знаю о производительности, но вы можете обойти этот вопрос все вместе, создав запрос перед его выполнением.Я думаю, что это улучшает читабельность кода и уменьшает путаницу.

public IEnumerable<TEntity> GetAll(TKey fKey)
{
    using (var context = new DbContext())
    {
        IQueryable<TEntity> query = context.Set<TEntity>();

        if (fKey != null)
        {
            query = query.Where(e => e.fKey == fKey);
        }

        return query.ToList();
    }
}

РЕДАКТИРОВАТЬ: При вызове редактирования вашего вопроса, я думаю, что следующий метод будет использовать то же самое, но избегает ненужных операторов в запросах SQL:

public IEnumerable<Entity> GetAll(
    Func<IQueryable<Entity>, IQueryable<Entity>> query)
{
    using (var context = new DbContext())
        return query(context.Set<Entity>).ToList();
}

// then use like this:
EntityRepository.GetAll((entities) =>
    {
        var query = entities;
        if (param1 != null) query = query.Where(e => e.field1 == param1);
        if (param2 != null) query = query.Where(e => e.field2 == param2);
        if (param3 != null) query = query.Where(e => e.field3 == param3);
        return query;
    });
...