Entity Framework, построение запроса на основе критериев - PullRequest
2 голосов
/ 05 декабря 2008

Мне было интересно, есть ли у кого-нибудь лучшая идея, как это сделать. Атм, возвращающий IQueryable<Member> как ObjectQuery<Member>, кажется мне грязным.

namespace Falcon.Business.Repositories
{
    using System;
    using System.Data.Objects;
    using System.Linq;
    using Falcon.Business.Criteria;
    using Falcon.Business.Entities;
    using Falcon.Business.Enums;
    using Falcon.Business.Extensions;
    using Falcon.Business.Repositories.Interfaces;
    using Falcon.Business.Services;
    using Falcon.Business.Services.Interfaces;
    using Falcon.Core.Extensions;

    public class MemberRepository : LinqRepository<Member>, IMemberRepository
    {
        public Member Fetch(MemberCriteria criteria)
        {
            ObjectQuery<Member> query = base.CreateQuery();

            query = this.AddRelations(query);
            query = this.AddCriteria(query, criteria);
            query = this.AddCriteriaOrder(query, criteria);

            return query.FirstOrDefault();
        }

        public IPagerService<Member> FetchAll(MemberCriteria criteria)
        {
            int page = (criteria.Page.HasValue) ? criteria.Page.Value : 1;
            int limit = criteria.Limit;
            int start = (page * limit) - limit;
            int total = this.Count(criteria);

            ObjectQuery<Member> query = base.CreateQuery();

            query = this.AddRelations(query);
            query = this.AddCriteria(query, criteria);
            query = this.AddCriteriaOrder(query, criteria);

            return new PagerService<Member>(query.Skip(start).Take(limit).ToList(), page, limit, total);
        }

        public int Count(MemberCriteria criteria)
        {
            ObjectQuery<Member> query = base.CreateQuery();

            query = this.AddCriteria(query, criteria);

            return query.Count();
        }

        public ObjectQuery<Member> AddCriteria(IQueryable<Member> query, MemberCriteria criteria)
        {
            if (criteria.Title.HasValue())
            {
                query = query.Where(q => q.Title == criteria.Title);
            }

            if (criteria.TitleUrl.HasValue())
            {
                query = query.Where(q => q.TitleUrl == criteria.TitleUrl);
            }

            if (criteria.EmailAddress.HasValue())
            {
                query = query.Where(q => q.EmailAddress == criteria.EmailAddress);
            }

            if (criteria.HostAddress.HasValue())
            {
                query = query.Where(q => q.HostAddress == criteria.HostAddress);
            }

            query = query.Where(q => q.Status == criteria.Status);

            return query as ObjectQuery<Member>;
        }

        public ObjectQuery<Member> AddCriteriaOrder(IQueryable<Member> query, MemberCriteria criteria)
        {
            if (criteria.Sort == SortMember.ID)
            {
                query = criteria.Order == SortOrder.Asc
                    ? query.OrderBy(q => q.ID)
                    : query.OrderByDescending(q => q.ID);
            }
            else if (criteria.Sort == SortMember.Posts)
            {
                query = criteria.Order == SortOrder.Asc
                    ? query.OrderBy(q => q.Posts)
                    : query.OrderByDescending(q => q.Posts);
            }
            else if (criteria.Sort == SortMember.Title)
            {
                query = criteria.Order == SortOrder.Asc
                    ? query.OrderBy(q => q.Title)
                    : query.OrderByDescending(q => q.Title);
            }
            else if (criteria.Sort == SortMember.LastLogin)
            {
                query = criteria.Order == SortOrder.Asc
                    ? query.OrderBy(q => q.LastLogin)
                    : query.OrderByDescending(q => q.LastLogin);
            }
            else if (criteria.Sort == SortMember.LastVisit)
            {
                query = criteria.Order == SortOrder.Asc
                    ? query.OrderBy(q => q.LastVisit)
                    : query.OrderByDescending(q => q.LastVisit);
            }
            else
            {
                query = criteria.Order == SortOrder.Asc
                    ? query.OrderBy(q => q.Created)
                    : query.OrderByDescending(q => q.Created);
            }

            return query as ObjectQuery<Member>;
        }

        private ObjectQuery<Member> AddRelations(ObjectQuery<Member> query)
        {
            query = query.Include(x => x.Country);
            query = query.Include(x => x.TimeZone);
            query = query.Include(x => x.Profile);

            return query;
        }
    }
}

1 Ответ

2 голосов
/ 14 декабря 2008

Мне также не нравится возвращать объектный запрос, потому что это сделает вас очень зависимым от Entity Framwork. Зная Microsoft, они, вероятно, внесли много изменений в версию 2, поэтому вы не хотите этого делать.

NHibernate использует критерии, как вы и предлагали, но их реализация гораздо более общая. Мне нравится более общая реализация, чем ваш пример, потому что тогда вам не нужно создавать критерии для каждого объекта. С другой стороны, ваша реализация типизирована, что тоже очень аккуратно. Если вы хотите получить лучшее из обоих, более общую реализацию, которая является типизированной, вы можете взглянуть на реализацию NHibernate, но вместо использования строк используйте лямбда-функции и обобщенные .Net. Я мог бы опубликовать пример, как это сделать, но сейчас я не на своей машине.

...