public override bool Execute(RockContext rockContext, WorkflowAction action, object entity, out List <string> errorMessages) { errorMessages = new List <string>(); EntityTypeCache cachedEntityType = EntityTypeCache.Read(GetAttributeValue(action, "EntityType").AsGuid()); if (cachedEntityType != null) { Type entityType = cachedEntityType.GetEntityType(); var newEntity = (IEntity)Activator.CreateInstance(entityType); var propertyValues = GetAttributeValue(action, "EntityProperties").Replace(" ! ", " | ").ResolveMergeFields(GetMergeFields(action)).TrimEnd('|').Split('|').Select(p => p.Split('^')).Select(p => new { Name = p[0], Value = p[1] }); foreach (var prop in propertyValues) { PropertyInfo propInf = entityType.GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance); if (null != propInf && propInf.CanWrite) { if (!(GetAttributeValue(action, "EmptyValueHandling") == "IGNORE" && string.IsNullOrWhiteSpace(prop.Value))) { try { propInf.SetValue(newEntity, ObjectConverter.ConvertObject(prop.Value, propInf.PropertyType, GetAttributeValue(action, "EmptyValueHandling") == "NULL"), null); } catch (Exception ex) when(ex is InvalidCastException || ex is FormatException || ex is OverflowException) { errorMessages.Add("Invalid Property Value: " + prop.Name + ": " + ex.Message); } } } else { errorMessages.Add("Invalid Property: " + prop.Name); } } rockContext.Set(entityType).Add(newEntity); rockContext.SaveChanges(); // If request attribute was specified, requery the request and set the attribute's value Guid?entityAttributeGuid = GetAttributeValue(action, "EntityAttribute").AsGuidOrNull(); if (entityAttributeGuid.HasValue) { newEntity = (IEntity)rockContext.Set(entityType).Find(new[] { newEntity.Id }); if (newEntity != null) { SetWorkflowAttributeValue(action, entityAttributeGuid.Value, newEntity.Guid.ToString()); } } return(true); } errorMessages.Add("Invalid Entity Attribute"); return(false); }
/// <summary> /// Gets the expression. /// </summary> /// <param name="context">The context.</param> /// <param name="entityIdProperty">The entity identifier property.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override Expression GetExpression(RockContext context, MemberExpression entityIdProperty, string selection) { // groupmembers var groupMembers = context.Set <Rock.Model.GroupMember>(); // m ParameterExpression groupMemberParameter = Expression.Parameter(typeof(Rock.Model.GroupMember), "m"); // m.PersonId MemberExpression memberPersonIdProperty = Expression.Property(groupMemberParameter, "PersonId"); // m.Group MemberExpression groupProperty = Expression.Property(groupMemberParameter, "Group"); // m.Group.GroupType MemberExpression groupTypeProperty = Expression.Property(groupProperty, "GroupType"); // m.Group.GroupType.Guid MemberExpression groupTypeGuidProperty = Expression.Property(groupTypeProperty, "Guid"); // family group type guid Expression groupTypeConstant = Expression.Constant(Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid()); // m.PersonId == p.Id Expression personCompare = Expression.Equal(memberPersonIdProperty, entityIdProperty); // m.Group.GroupType.Guid == GROUPTYPE_FAMILY guid Expression groupTypeCompare = Expression.Equal(groupTypeGuidProperty, groupTypeConstant); // m.PersonID == p.Id && m.Group.GroupType.Guid == GROUPTYPE_FAMILY guid Expression andExpression = Expression.And(personCompare, groupTypeCompare); // m => m.PersonID == p.Id && m.Group.GroupType.Guid == GROUPTYPE_FAMILY guid var compare = new Expression[] { Expression.Constant(groupMembers), Expression.Lambda <Func <Rock.Model.GroupMember, bool> >(andExpression, new ParameterExpression[] { groupMemberParameter }) }; // groupmembers.Where(m => m.PersonID == p.Id && m.Group.GroupType.Guid == GROUPTYPE_FAMILY guid) Expression whereExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(Rock.Model.GroupMember) }, compare); // m.Group.Name MemberExpression groupName = Expression.Property(groupProperty, "Name"); // m => m.Group.Name Expression groupNameLambda = Expression.Lambda(groupName, new ParameterExpression[] { groupMemberParameter }); // groupmembers.Where(m => m.PersonID == p.Id && m.Group.GroupType.Guid == GROUPTYPE_FAMILY guid).Select( m => m.Group.Name); Expression selectName = Expression.Call(typeof(Queryable), "Select", new Type[] { typeof(Rock.Model.GroupMember), typeof(string) }, whereExpression, groupNameLambda); // groupmembers.Where(m => m.PersonID == p.Id && m.Group.GroupType.Guid == GROUPTYPE_FAMILY guid).Select( m => m.Group.Name).FirstOrDefault(); Expression firstOrDefault = Expression.Call(typeof(Queryable), "FirstOrDefault", new Type[] { typeof(string) }, selectName); return(firstOrDefault); }
/// <summary> /// Gets the expression. /// </summary> /// <param name="context">The context.</param> /// <param name="entityIdProperty">The entity identifier property.</param> /// <param name="selection"></param> /// <returns></returns> public override Expression GetExpression(RockContext context, Expression entityIdProperty, string selection) { // transactions var transactionDetails = context.Set <FinancialTransactionDetail>(); // t ParameterExpression transactionDetailParameter = Expression.Parameter(typeof(FinancialTransactionDetail), "t"); // t.Transaction MemberExpression transactionProperty = Expression.Property(transactionDetailParameter, "Transaction"); // t.Transaction.AuthorizedPersonId MemberExpression authorizedPersonIdProperty = Expression.Property(transactionProperty, "AuthorizedPersonId"); // t.Transaction.AuthorizedPersonId == Convert(p.Id) Expression whereClause = Expression.Equal(authorizedPersonIdProperty, Expression.Convert(entityIdProperty, typeof(int?))); // get the selected AccountId(s). If there are any, limit to transactions that for that Account if (!string.IsNullOrWhiteSpace(selection)) { // accountIds var selectedAccountIdList = selection.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(a => a.AsInteger() ?? 0).ToList(); if (selectedAccountIdList.Count() > 0) { // t.AccountId MemberExpression accountIdProperty = Expression.Property(transactionDetailParameter, "AccountId"); // accountIds.Contains(t.AccountId) Expression selectedAccountIds = Expression.Constant(selectedAccountIdList); Expression containsExpression = Expression.Call(selectedAccountIds, "Contains", new Type[] {}, accountIdProperty); // t.authorizedPersonId == Convert(p.Id) && accountIds.Contains(t.AccountId) whereClause = Expression.And(whereClause, containsExpression); } } // t => t.Transaction.AuthorizedPersonId == Convert(p.Id) var compare = new Expression[] { Expression.Constant(transactionDetails), Expression.Lambda <Func <FinancialTransactionDetail, bool> >(whereClause, new ParameterExpression[] { transactionDetailParameter }) }; // transactions.Where( t => t.Transaction.AuthorizedPersonId == Convert(p.Id) Expression whereExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(FinancialTransactionDetail) }, compare); // t.Transaction.TransactionDateTime MemberExpression transactionDateTime = Expression.Property(transactionProperty, "TransactionDateTime"); // t => t.Transaction.transactionDateTime var transactionDate = Expression.Lambda <Func <FinancialTransactionDetail, DateTime?> >(transactionDateTime, new ParameterExpression[] { transactionDetailParameter }); // transaction.Where( t => t.Transaction.AuthorizedPersonId == Convert(p.Id).Max( t => t.Transaction.transactionDateTime) Expression maxExpression = Expression.Call(typeof(Queryable), "Max", new Type[] { typeof(FinancialTransactionDetail), typeof(DateTime? ) }, whereExpression, transactionDate); return(maxExpression); }
/// <summary> /// Gets the expression. /// </summary> /// <param name="context">The context.</param> /// <param name="entityIdProperty">The entity identifier property.</param> /// <param name="selection"></param> /// <returns></returns> public override Expression GetExpression(RockContext context, MemberExpression entityIdProperty, string selection) { // transactions var transactionDetails = context.Set <FinancialTransactionDetail>(); // t ParameterExpression transactionDetailParameter = Expression.Parameter(typeof(FinancialTransactionDetail), "t"); // t.Transaction MemberExpression transactionProperty = Expression.Property(transactionDetailParameter, "Transaction"); // t.Transaction.AuthorizedPersonAlias MemberExpression authorizedPersonAliasProperty = Expression.Property(transactionProperty, "AuthorizedPersonAlias"); // t.Transaction.AuthorizedPersonAlias.PersonId MemberExpression authorizedPersonIdProperty = Expression.Property(authorizedPersonAliasProperty, "PersonId"); // t.Transaction.AuthorizedPersonAlias.PersonId == Convert(p.Id) Expression whereClause = Expression.Equal(authorizedPersonIdProperty, Expression.Convert(entityIdProperty, typeof(int))); // t.Transaction.TransactionTypeValueId MemberExpression transactionTypeValueIdProperty = Expression.Property(transactionProperty, "TransactionTypeValueId"); int transactionTypeContributionId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id; // t.Transaction.TransactionTypeValueId == transactionTypeContributionId whereClause = Expression.And(whereClause, Expression.Equal(transactionTypeValueIdProperty, Expression.Constant(transactionTypeContributionId))); // get the selected AccountId(s). If there are any, limit to transactions that for that Account if (!string.IsNullOrWhiteSpace(selection)) { // accountIds var selectedAccountGuidList = selection.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).AsGuidList(); var selectedAccountIdList = new FinancialAccountService(context).GetByGuids(selectedAccountGuidList).Select(a => a.Id).ToList(); if (selectedAccountIdList.Count() > 0) { // t.AccountId MemberExpression accountIdProperty = Expression.Property(transactionDetailParameter, "AccountId"); // accountIds.Contains(t.AccountId) Expression selectedAccountIds = Expression.Constant(selectedAccountIdList); Expression containsExpression = Expression.Call(selectedAccountIds, "Contains", new Type[] { }, accountIdProperty); // t.authorizedPersonId == Convert(p.Id) && accountIds.Contains(t.AccountId) whereClause = Expression.And(whereClause, containsExpression); } } // t => t.Transaction.AuthorizedPersonId == Convert(p.Id) var compare = new Expression[] { Expression.Constant(transactionDetails), Expression.Lambda <Func <FinancialTransactionDetail, bool> >(whereClause, new ParameterExpression[] { transactionDetailParameter }) }; // transactions.Where( t => t.Transaction.AuthorizedPersonId == Convert(p.Id) Expression whereExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(FinancialTransactionDetail) }, compare); // t.Transaction.TransactionDateTime MemberExpression transactionDateTime = Expression.Property(transactionProperty, "SundayDate"); // t => t.Transaction.transactionDateTime var transactionDate = Expression.Lambda <Func <FinancialTransactionDetail, DateTime?> >(transactionDateTime, new ParameterExpression[] { transactionDetailParameter }); // transaction.Where( t => t.Transaction.AuthorizedPersonId == Convert(p.Id).Max( t => t.Transaction.transactionDateTime) string methodName = FirstOrLast == FirstLast.Last ? "Max" : "Min"; Expression maxMinExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { typeof(FinancialTransactionDetail), typeof(DateTime? ) }, whereExpression, transactionDate); return(maxMinExpression); }
/// <summary> /// Renders the specified context. /// </summary> /// <param name="context">The context.</param> /// <param name="result">The result.</param> /// <exception cref="System.Exception">Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist.</exception> public override void Render(Context context, TextWriter result) { // first ensure that entity commands are allowed in the context if (!this.IsAuthorized(context)) { result.Write(string.Format(RockLavaBlockBase.NotAuthorizedMessage, this.Name)); base.Render(context, result); return; } bool hasFilter = false; // get a service for the entity based off it's friendly name var entityTypes = EntityTypeCache.All(); var model = string.Empty; if (_entityName == "business") { model = "Rock.Model.Person"; } else { model = "Rock.Model." + _entityName; } // Check first to see if this is a core model var entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, model, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); // If not, look for first plugin model that has same friendly name if (entityTypeCache == null) { entityTypeCache = entityTypes .Where(e => e.IsEntity && !e.Name.StartsWith("Rock.Model") && e.FriendlyName != null && e.FriendlyName.RemoveSpaces().ToLower() == _entityName) .OrderBy(e => e.Id) .FirstOrDefault(); } // If still null check to see if this was a duplicate class and full class name was used as entity name if (entityTypeCache == null) { model = _entityName.Replace('_', '.'); entityTypeCache = entityTypes.Where(e => String.Equals(e.Name, model, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); } if (entityTypeCache != null) { Type entityType = entityTypeCache.GetEntityType(); if (entityType != null) { // Get the database context Type contextType = null; Rock.Data.DbContext dbContext = null; var contexts = Rock.Reflection.SearchAssembly(entityType.Assembly, typeof(Rock.Data.DbContext)); if (contexts.Any()) { contextType = contexts.First().Value; dbContext = Activator.CreateInstance(contextType) as Rock.Data.DbContext; } if (dbContext == null) { dbContext = _rockContext; } // create an instance of the entity's service Type[] modelType = { entityType }; Type genericServiceType = typeof(Rock.Data.Service <>); Type modelServiceType = genericServiceType.MakeGenericType(modelType); Rock.Data.IService serviceInstance = Activator.CreateInstance(modelServiceType, new object[] { dbContext }) as IService; ParameterExpression paramExpression = Expression.Parameter(entityType, "x"); Expression queryExpression = null; // the base expression we'll use to build our query from // parse markup var parms = ParseMarkup(_markup, context); if (parms.Any(p => p.Key == "id")) { string propertyName = "Id"; List <string> selectionParms = new List <string>(); selectionParms.Add(PropertyComparisonConverstion("==").ToString()); selectionParms.Add(parms["id"].ToString()); selectionParms.Add(propertyName); var entityProperty = entityType.GetProperty(propertyName); queryExpression = ExpressionHelper.PropertyFilterExpression(selectionParms, paramExpression, propertyName, entityProperty.PropertyType); hasFilter = true; } else { // where clause expression if (parms.Any(p => p.Key == "where")) { queryExpression = ParseWhere(parms["where"], entityType, serviceInstance, paramExpression, entityType, entityTypeCache); if (queryExpression != null) { hasFilter = true; } } // dataview expression if (parms.Any(p => p.Key == "dataview")) { var dataViewId = parms["dataview"].AsIntegerOrNull(); if (dataViewId.HasValue) { var dataViewExpression = GetDataViewExpression(dataViewId.Value, serviceInstance, paramExpression, entityTypeCache); if (queryExpression == null) { queryExpression = dataViewExpression; hasFilter = true; } else { queryExpression = Expression.AndAlso(queryExpression, dataViewExpression); } } } // process dynamic filter expressions (from the query string) if (parms.Any(p => p.Key == "dynamicparameters")) { var dynamicFilters = parms["dynamicparameters"].Split(',') .Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x)) .ToList(); foreach (var dynamicFilter in dynamicFilters) { var dynamicFilterValue = HttpContext.Current.Request[dynamicFilter]; var dynamicFilterExpression = GetDynamicFilterExpression(dynamicFilter, dynamicFilterValue, entityType, serviceInstance, paramExpression); if (dynamicFilterExpression != null) { if (queryExpression == null) { queryExpression = dynamicFilterExpression; hasFilter = true; } else { queryExpression = Expression.AndAlso(queryExpression, dynamicFilterExpression); } } } } } // make the query from the expression MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(Rock.Web.UI.Controls.SortProperty), typeof(int?) }); if (getMethod != null) { var queryResult = getMethod.Invoke(serviceInstance, new object[] { paramExpression, queryExpression, null, null }) as IQueryable <IEntity>; // process entity specific filters switch (_entityName) { case "person": { queryResult = PersonFilters((IQueryable <Person>)queryResult, parms); break; } case "business": { queryResult = BusinessFilters((IQueryable <Person>)queryResult, parms); break; } } // if there was a dynamic expression add it now if (parms.Any(p => p.Key == "expression")) { queryResult = queryResult.Where(parms["expression"]); hasFilter = true; } // get a listing of ids if (parms.Any(p => p.Key == "ids")) { var value = parms["ids"].ToString().Split(',').Select(int.Parse).ToList(); queryResult = queryResult.Where(x => value.Contains(x.Id)); hasFilter = true; } var queryResultExpression = queryResult.Expression; // add sort expressions if (parms.Any(p => p.Key == "sort")) { string orderByMethod = "OrderBy"; foreach (var column in parms["sort"].Split(',').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList()) { string propertyName; var direction = SortDirection.Ascending; if (column.EndsWith(" desc", StringComparison.OrdinalIgnoreCase)) { direction = SortDirection.Descending; propertyName = column.Left(column.Length - 5); } else { propertyName = column; } string methodName = direction == SortDirection.Descending ? orderByMethod + "Descending" : orderByMethod; if (entityType.GetProperty(propertyName) != null) { // sorting a entity property var memberExpression = Expression.Property(paramExpression, propertyName); LambdaExpression sortSelector = Expression.Lambda(memberExpression, paramExpression); queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector); } else { // sorting on an attribute // get attribute id int?attributeId = null; foreach (var id in AttributeCache.GetByEntity(entityTypeCache.Id).SelectMany(a => a.AttributeIds)) { var attribute = AttributeCache.Get(id); if (attribute.Key == propertyName) { attributeId = id; } } if (attributeId.HasValue) { // get AttributeValue queryable and parameter var attributeValues = _rockContext.Set <AttributeValue>(); ParameterExpression attributeValueParameter = Expression.Parameter(typeof(AttributeValue), "v"); MemberExpression idExpression = Expression.Property(paramExpression, "Id"); var attributeExpression = Attribute.Helper.GetAttributeValueExpression(attributeValues, attributeValueParameter, idExpression, attributeId.Value); LambdaExpression sortSelector = Expression.Lambda(attributeExpression, paramExpression); queryResultExpression = Expression.Call(typeof(Queryable), methodName, new Type[] { queryResult.ElementType, sortSelector.ReturnType }, queryResultExpression, sortSelector); } } orderByMethod = "ThenBy"; } } // reassemble the queryable with the sort expressions queryResult = queryResult.Provider.CreateQuery(queryResultExpression) as IQueryable <IEntity>; if (parms.GetValueOrNull("count").AsBoolean()) { int countResult = queryResult.Count(); context.Scopes.Last()["count"] = countResult; } else { // run security check on each result var items = queryResult.ToList(); var itemsSecured = new List <IEntity>(); Person person = GetCurrentPerson(context); foreach (IEntity item in items) { ISecured itemSecured = item as ISecured; if (itemSecured == null || itemSecured.IsAuthorized(Authorization.VIEW, person)) { itemsSecured.Add(item); } } queryResult = itemsSecured.AsQueryable(); // offset if (parms.Any(p => p.Key == "offset")) { queryResult = queryResult.Skip(parms["offset"].AsInteger()); } // limit, default to 1000 if (parms.Any(p => p.Key == "limit")) { queryResult = queryResult.Take(parms["limit"].AsInteger()); } else { queryResult = queryResult.Take(1000); } // check to ensure we had some form of filter (otherwise we'll return all results in the table) if (!hasFilter) { throw new Exception("Your Lava command must contain at least one valid filter. If you configured a filter it's possible that the property or attribute you provided does not exist."); } var resultList = queryResult.ToList(); // if there is only one item to return set an alternative non-array based variable if (resultList.Count == 1) { context.Scopes.Last()[_entityName] = resultList.FirstOrDefault(); } context.Scopes.Last()[parms["iterator"]] = resultList; } } } } else { result.Write(string.Format("Could not find a model for {0}.", _entityName)); base.Render(context, result); } base.Render(context, result); }
/// <summary> /// Gets the data source. /// </summary> /// <param name="context">The context.</param> /// <param name="entityType">Type of the entity.</param> /// <param name="entityFields">The entity fields.</param> /// <param name="attributes">The attributes.</param> /// <param name="selectComponents">The select components.</param> /// <param name="sortProperty">The sort property.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> public List <object> GetDataSource(RockContext context, Type entityType, Dictionary <int, EntityField> entityFields, Dictionary <int, AttributeCache> attributes, Dictionary <int, ReportField> selectComponents, Rock.Web.UI.Controls.SortProperty sortProperty, out List <string> errorMessages) { errorMessages = new List <string>(); if (entityType != null) { Type[] modelType = { entityType }; Type genericServiceType = typeof(Rock.Data.Service <>); Type modelServiceType = genericServiceType.MakeGenericType(modelType); object serviceInstance = Activator.CreateInstance(modelServiceType, new object[] { context }); if (serviceInstance != null) { ParameterExpression paramExpression = serviceInstance.GetType().GetProperty("ParameterExpression").GetValue(serviceInstance) as ParameterExpression; MemberExpression idExpression = Expression.Property(paramExpression, "Id"); // Get AttributeValue queryable and parameter var attributeValues = context.Set <AttributeValue>(); ParameterExpression attributeValueParameter = Expression.Parameter(typeof(AttributeValue), "v"); // Create the dynamic type var dynamicFields = new Dictionary <string, Type>(); foreach (var f in entityFields) { dynamicFields.Add(string.Format("Entity_{0}_{1}", f.Value.Name, f.Key), f.Value.PropertyType); } foreach (var a in attributes) { dynamicFields.Add(string.Format("Attribute_{0}_{1}", a.Value.Id, a.Key), typeof(string)); } foreach (var reportField in selectComponents) { DataSelectComponent selectComponent = DataSelectContainer.GetComponent(reportField.Value.DataSelectComponentEntityType.Name); if (selectComponent != null) { dynamicFields.Add(string.Format("Data_{0}_{1}", selectComponent.ColumnPropertyName, reportField.Key), selectComponent.ColumnFieldType); } } if (dynamicFields.Count == 0) { errorMessages.Add("At least one field must be defined"); return(null); } Type dynamicType = LinqRuntimeTypeBuilder.GetDynamicType(dynamicFields); ConstructorInfo methodFromHandle = dynamicType.GetConstructor(Type.EmptyTypes); // Bind the dynamic fields to their expressions var bindings = new List <MemberBinding>(); foreach (var f in entityFields) { bindings.Add(Expression.Bind(dynamicType.GetField(string.Format("entity_{0}_{1}", f.Value.Name, f.Key)), Expression.Property(paramExpression, f.Value.Name))); } foreach (var a in attributes) { bindings.Add(Expression.Bind(dynamicType.GetField(string.Format("attribute_{0}_{1}", a.Value.Id, a.Key)), GetAttributeValueExpression(attributeValues, attributeValueParameter, idExpression, a.Value.Id))); } foreach (var reportField in selectComponents) { DataSelectComponent selectComponent = DataSelectContainer.GetComponent(reportField.Value.DataSelectComponentEntityType.Name); if (selectComponent != null) { bindings.Add(Expression.Bind(dynamicType.GetField(string.Format("data_{0}_{1}", selectComponent.ColumnPropertyName, reportField.Key)), selectComponent.GetExpression(context, idExpression, reportField.Value.Selection))); } } ConstructorInfo constructorInfo = dynamicType.GetConstructor(Type.EmptyTypes); NewExpression newExpression = Expression.New(constructorInfo); MemberInitExpression memberInitExpression = Expression.MemberInit(newExpression, bindings); Expression selector = Expression.Lambda(memberInitExpression, paramExpression); Expression whereExpression = this.DataView.GetExpression(serviceInstance, paramExpression, out errorMessages); MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(Rock.Web.UI.Controls.SortProperty) }); if (getMethod != null) { var getResult = getMethod.Invoke(serviceInstance, new object[] { paramExpression, whereExpression, sortProperty }); var qry = getResult as IQueryable <IEntity>; var selectExpression = Expression.Call(typeof(Queryable), "Select", new Type[] { qry.ElementType, dynamicType }, Expression.Constant(qry), selector); var query = qry.Provider.CreateQuery(selectExpression).AsNoTracking(); // enumerate thru the query results and put into a list var reportResult = new List <object>(); var enumerator = query.GetEnumerator(); while (enumerator.MoveNext()) { reportResult.Add(enumerator.Current); } return(reportResult); } } } return(null); }