суббота, 10 апреля 2010 г.

Entity Framework 4 & Func предикат



В одном и проектов был разработан слой доступа к данным через паттерн Repository и Entity Framework 4 (code only). Интерфейс репозтория выглядел следующим образом:

public interface IRepository<T> where T : class
{
    IEnumerable<T> Find(Func<T, bool>; where);
        
    IEnumerable<T> Find(Specification<T> specification);

    T Single(Func<T, bool> where);

    T Single(Specification<T> specification);

    void Delete(T entity);

    void Add(T entity);
}

Пока все хорошо, но при реализации первого же метода и анализе запроса к базе данных было обнаружено (совсем не обноружено) что отсутствует условие. Т.е. запрос к базе приходит на выборку всех данных и их последующую обработку на стороне клиента (клиент по отношению к базе данных). Конечно, это не простительное убийство ресурсов машины.

Решение очень протое. Вместо использования предикатов типа:

Func<T, bool>
необходимо использовать:
Expression<Func<TEntity, bool>>

Для полноты приведу пример реализации интерфейса репозитория

public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private readonly IObjectContext _objectContext = null;
    private readonly IObjectSet<TEntity> _objectSet = null;

    public BaseRepository(IObjectContext objectContext)
    {
        if (objectContext == null)
            throw new ArgumentNullException("objectContext");

        _objectContext = objectContext;
        _objectSet = _objectContext.CreateObjectSet<TEntity>();
    }

    protected IQueryable<TEntity> GetQuery()
    {
        return _objectSet;
    }

    public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> where)
    {
        return _objectSet.Where(where);
    }

    public IEnumerable<TEntity> Find(Specification<TEntity> specification)
    {
        return specification.SatisfyingElementsFrom(GetQuery());
    }

    public TEntity Single(Specification<TEntity> specification)
    {
        return _objectSet.SingleOrDefault(specification.MatchingCriteria);
    }

    public TEntity Single(Expression<Func<TEntity, bool>> where)
    {
        return _objectSet.SingleOrDefault(where);
    }

    public void Delete(TEntity entity)
    {
        _objectSet.DeleteObject(entity);
    }

    public void Add(TEntity entity)
    {
        _objectSet.AddObject(entity);
    }
}

Полезные ссылки:


Newer Posts Older Posts