2012-08-14 58 views
1

我已经构建了一个基本上基于Scott Millett的“专业ASP.NET设计模式”中的示例来公开IEnumerable的存储库。基于存储库的EF查询对象模式示例

但是,因为他主要使用NHibernate,他如何实现查询对象模式的示例,或者更确切地说,如何最好地将查询翻译成EF中有用的东西,有点欠缺。

我正在寻找一个使用EF4实现查询对象模式的好例子。

编辑:在本书中的简单示例的主要问题是,CreateQueryAndObjectParameters只处理2个情况,等于& LesserThanOrEqual - 不完全是一个完整的查询解决方案。它使用一个字符串来构建标准 - 与NHibernate相比,这是一种非常粗糙的处理方式。他说他会提供第10章示例的EF代码,但它不在下载中。因此寻找一个真实世界的例子。

回答

2

在这一点上,您可能已经厌倦了我的消息,但本机支持的IQueryable是EF所需的唯一查询对象模式实现。

+0

感谢 - 这是我采取的办法该项目:)虽然我真的仍然希望看到这样的实施感兴趣。 – 2012-09-05 20:37:51

+0

@Dale Burrell,你为什么认为'IQueryable'不符合“查询对象模式”的实现? – smartcaveman 2012-09-30 22:45:22

0

根据这本书( “专业ASP.NET设计模式” 由斯科特·米利特),您可以使用此代码[我已经改进了一些行]:

  • 基础设施层:

  • 标准类:(每个查询可以包含一些判据)

    public class Criterion 
    { 
    private string _propertyName; 
    private object _value; 
    private CriteriaOperator _criteriaOperator; 
    
    public Criterion(string propertyName, object value, 
           CriteriaOperator criteriaOperator) 
    { 
        _propertyName = propertyName; 
        _value = value; 
        _criteriaOperator = criteriaOperator; 
    } 
    
    public string PropertyName 
    { 
        get { return _propertyName; } 
    } 
    
    public object Value 
    { 
        get { return _value; } 
    } 
    
    public CriteriaOperator criteriaOperator 
    { 
        get { return _criteriaOperator; } 
    } 
    
    public static Criterion Create<T>(Expression<Func<T, object>> expression, object value, CriteriaOperator criteriaOperator) 
    { 
        string propertyName = PropertyNameHelper.ResolvePropertyName<T>(expression); 
        Criterion myCriterion = new Criterion(propertyName, value, criteriaOperator); 
        return myCriterion; 
    } 
    } 
    
  • CriteriaOperato R类别:

    public enum CriteriaOperator 
    { 
        Equal, 
        LesserThanOrEqual, 
        NotApplicable 
        // TODO: Add the remainder of the criteria operators as required. 
    } 
    
  • OrderByClause类:

    public class OrderByClause 
    { 
        public string PropertyName { get; set; } 
        public bool Desc { get; set; } 
    } 
    
  • 查询类:

    public class Query 
    { 
    private QueryName _name; 
    private IList<Query> _subQueries = new List<Query>(); 
    private IList<Criterion> _criteria = new List<Criterion>(); 
    
    public Query() 
        : this(QueryName.Dynamic, new List<Criterion>()) 
    { } 
    
    public Query(QueryName name, IList<Criterion> criteria) 
    { 
        _name = name; 
        _criteria = criteria; 
    } 
    
    public QueryName Name 
    { 
        get { return _name; } 
    } 
    
    public bool IsNamedQuery() 
    { 
        return Name != QueryName.Dynamic; 
    } 
    
    public IEnumerable<Criterion> Criteria 
    { 
        get {return _criteria ;} 
    }   
    
    public void Add(Criterion criterion) 
    { 
        if (!IsNamedQuery()) 
         _criteria.Add(criterion); 
        else 
         throw new ApplicationException("You cannot add additional criteria to named queries"); 
    } 
    
    public IEnumerable<Query> SubQueries 
    { 
        get { return _subQueries; } 
    } 
    
    public void AddSubQuery(Query subQuery) 
    { 
        _subQueries.Add(subQuery); 
    } 
    
    public QueryOperator QueryOperator { get; set; } 
    
    public OrderByClause OrderByProperty { get; set; } 
    } 
    
  • PropertyNameHelper类:

    public static class PropertyNameHelper 
    { 
        public static string ResolvePropertyName<T>(
             Expression<Func<T, object>> expression) 
        { 
         var expr = expression.Body as MemberExpression; 
         if (expr == null) 
         { 
          var u = expression.Body as UnaryExpression; 
          expr = u.Operand as MemberExpression; 
         } 
         return expr.ToString().Substring(expr.ToString().IndexOf(".") + 1); 
        } 
    } 
    

    您需要一个QueryTranslator课呢,翻译查询(在库层):

    public class TimelogQueryTranslator : QueryTranslator 
    { 
    public ObjectQuery<Timelog> Translate(Query query) 
    { 
        ObjectQuery<Timelog> timelogQuery; 
    
        if (query.IsNamedQuery()) 
        { 
         timelogQuery = FindEFQueryFor(query); 
        } 
        else 
        { 
         StringBuilder queryBuilder = new StringBuilder(); 
         IList<ObjectParameter> paraColl = new List<ObjectParameter>(); 
         CreateQueryAndObjectParameters(query, queryBuilder, paraColl); 
    
         //[Edited By= Iman] : 
         if (query.OrderByProperty == null) 
         { 
          timelogQuery = DataContextFactory.GetDataContext().Timelogs 
          .Where(queryBuilder.ToString(), paraColl.ToArray()); 
         } 
         else if (query.OrderByProperty.Desc == true) 
         { 
          timelogQuery = DataContextFactory.GetDataContext().Timelogs 
          .Where(queryBuilder.ToString(), paraColl.ToArray()).OrderBy(String.Format("it.{0} desc", query.OrderByProperty.PropertyName)); 
         } 
         else 
         { 
          timelogQuery = DataContextFactory.GetDataContext().Timelogs 
           .Where(queryBuilder.ToString(), paraColl.ToArray()).OrderBy(String.Format("it.{0} asc", query.OrderByProperty.PropertyName)); 
         } 
         //[Edited By= Iman] . 
    
        } 
    
        return timelogQuery; 
    } 
    //------------------------------------------------------------- 
        public abstract class QueryTranslator 
    { 
        public void CreateQueryAndObjectParameters(Query query, StringBuilder queryBuilder, IList<ObjectParameter> paraColl) 
        { 
         bool _isNotFirstFilterClause = false; 
    
         foreach (Criterion criterion in query.Criteria) 
         { 
          if (_isNotFirstFilterClause) 
          { 
           queryBuilder.Append(" AND "); //TODO: select depending on query.QueryOperator 
          } 
          switch (criterion.criteriaOperator) 
          { 
           case CriteriaOperator.Equal: 
            queryBuilder.Append(String.Format("it.{0} = @{0}", criterion.PropertyName)); 
            break; 
           case CriteriaOperator.LesserThanOrEqual: 
            queryBuilder.Append(String.Format("it.{0} <= @{0}", criterion.PropertyName)); 
            break; 
           default: 
            throw new ApplicationException("No operator defined"); 
          } 
    
          paraColl.Add(new ObjectParameter(criterion.PropertyName, criterion.Value)); 
    
          _isNotFirstFilterClause = true; 
         } 
        } 
    } 
    
服务层

现在:

public IEnumerable<Timelog> GetAllTimelogsFor(int iadcId, byte workShift) 
    { 
     Query query = new Query(QueryName.Dynamic,new List<Criterion>()); 
     query.Add(Criterion.Create<Timelog>(t=>t.IadcId, iadcId, CriteriaOperator.Equal)); 
     query.QueryOperator = QueryOperator.And; 
     query.Add(Criterion.Create<Timelog>(t=>t.Shift, workShift, CriteriaOperator.Equal)); 
     query.OrderByProperty = new OrderByClause { PropertyName = "FromTime", Desc = false }; 

     IEnumerable<Timelog> timelogs = _timelogRepository.FindBy(query); 

     return timelogs; 
    } 
+0

谢谢伊曼 - 正如前面提到的我拥有这本书,所以它非常专注于您再次输入所有内容:)不幸的是,虽然这是一个微不足道的例子(如在书中),但他表示他会提供章节的EF代码10,但不能下载。该示例的主要问题是CreateQueryAndObjectParameters仅处理2种情况,即Equal&LesserThanOrEqual - 不完全是一个完整的查询解决方案。与NHibernate相比,使用字符串来构建标准是一种非常粗糙的处理方式 - 我希望有人能有更好的东西。不管怎么说,还是要谢谢你。 – 2013-07-25 20:51:06