public override IEnumerable <System.Linq.Expressions.MemberBinding> InnerSelectBindings(Type selectType, System.Linq.Expressions.ParameterExpression sourceTypeParameter) { //the earliest encounter date that satisfies the query critieria ParameterExpression pe_sourceQueryType = sourceTypeParameter; Expression encountersProp = Expressions.AsQueryable(Expression.Property(pe_sourceQueryType, "Encounters")); ParameterExpression pe_encountersQueryType = Expression.Parameter(typeof(PCORIQueryBuilder.Model.Encounter), "enc"); Expression admittedOnSelector = Expression.Property(pe_encountersQueryType, "AdmittedOn"); BinaryExpression be_encounterPatient = Expression.Equal(Expression.Property(pe_sourceQueryType, "ID"), Expression.Property(pe_encountersQueryType, "PatientID")); BinaryExpression predicate = be_encounterPatient; if (Criteria.Any(c => c.Terms.Any(t => t.Type == ModelTermsFactory.ObservationPeriodID))) { var observationPeriodCriteria = Criteria.SelectMany(c => c.Terms.Where(t => t.Type == ModelTermsFactory.ObservationPeriodID)); foreach (var obpTerm in observationPeriodCriteria) { DateTime dateValue; var range = AdapterHelpers.ParseDateRangeValues(obpTerm); if (range.StartDate.HasValue) { dateValue = range.StartDate.Value.DateTime.Date; predicate = Expression.AndAlso(predicate, Expression.GreaterThanOrEqual(admittedOnSelector, Expression.Constant(dateValue))); } if (range.EndDate.HasValue) { dateValue = range.EndDate.Value.DateTime.Date; predicate = Expression.AndAlso(predicate, Expression.LessThanOrEqual(admittedOnSelector, Expression.Constant(dateValue))); } } } MethodCallExpression admittedOnWhere = Expressions.Where(encountersProp, Expression.Lambda(predicate, pe_encountersQueryType)); MethodCallExpression orderByAdmittedOn = Expressions.OrderByAscending(admittedOnWhere, Expression.Lambda(admittedOnSelector, pe_encountersQueryType)); //need to cast the return type of the select to a nullable datetime so that the FirstOrDefault will be null as the default MethodCallExpression admittedOnSelect = Expressions.Select(pe_encountersQueryType.Type, typeof(DateTime?), orderByAdmittedOn, Expression.Lambda(Expression.Convert(admittedOnSelector, typeof(DateTime?)), pe_encountersQueryType)); MethodCallExpression firstOrDefaultAdmittedOn = Expressions.FirstOrDefault <DateTime?>(admittedOnSelect); if (!HasStratifications) { return(new[] { Expression.Bind(selectType.GetProperty("AdmittedOn"), firstOrDefaultAdmittedOn) }); } //if stratified by Month -> return as string in format yyyy-MM //if stratified by Year -> return as string in format yyyy DTO.Enums.PeriodStratification stratification; if (!Enum.TryParse <DTO.Enums.PeriodStratification>(Stratifications.First().ToString(), out stratification)) { throw new ArgumentException("Unable to parse the specified stratification value as an PeriodStratification: " + Stratifications.First().ToString()); } Expression prop = Expression.Property(firstOrDefaultAdmittedOn, "Value"); //Expression yearPartString = Expressions.CallToString<int>(Expression.Property(prop, "Year")); //if (stratification == DTO.Enums.PeriodStratification.Monthly) //{ // //if stratified by Month -> return as string in format yyyy-MM // Expression monthPartString = Expressions.CallToString<int>(Expression.Property(prop, "Month")); // prop = Expressions.ConcatStrings(yearPartString, Expression.Constant("-"), monthPartString); //} //else if (stratification == DTO.Enums.PeriodStratification.Yearly) //{ // //if stratified by Year -> return as string in format yyyy // prop = yearPartString; //} //else //{ // throw new NotSupportedException("The specified period stratifcation is not currently supported; stratification value: " + Stratifications.First().ToString()); //} //Expression stratificationModifier = Expression.Condition(Expression.NotEqual(firstOrDefaultAdmittedOn, Expression.Constant(null)), prop, Expression.Constant("", typeof(string))); //return new[] { // Expression.Bind(selectType.GetProperty("AdmittedOn"), stratificationModifier) // }; Expression yearProp = Expression.Property(prop, "Year"); Expression monthProp = Expression.Property(prop, "Month"); return(new[] { Expression.Bind(selectType.GetProperty("AdmittedOn"), firstOrDefaultAdmittedOn), Expression.Bind(selectType.GetProperty("AdmittedOnYear"), yearProp), Expression.Bind(selectType.GetProperty("AdmittedOnMonth"), monthProp) }); }