private List <MedicalItem> GetMedicalItems()
        {
            RockContext  rockContext    = new RockContext();
            GroupService groupService   = new GroupService(rockContext);
            var          groupIdStrings = GetAttributeValue("GroupIds").SplitDelimitedValues();
            var          groupIds       = new List <int>();

            foreach (var id in groupIdStrings)
            {
                groupIds.Add(id.AsInteger());
            }

            var groups = groupService.GetByIds(groupIds);

            var groupTypeIds = groups.ToList().Select(g => g.GroupTypeId.ToString()).Distinct();

            var groupEntityid = EntityTypeCache.GetId <Rock.Model.GroupMember>();
            var key           = GetAttributeValue("MedicationMatrixKey");

            AttributeService attributeService = new AttributeService(rockContext);

            List <int> attributeIds = attributeService.Queryable()
                                      .Where(a =>
                                             (groupIdStrings.Contains(a.EntityTypeQualifierValue) || groupTypeIds.Contains(a.EntityTypeQualifierValue)) &&
                                             a.Key == key &&
                                             a.EntityTypeId == groupEntityid)
                                      .Select(a => a.Id).ToList();

            if (attributeIds == null)
            {
                nbAlert.Visible = true;
                nbAlert.Text    = "Medication attribute not found";
                return(null);
            }

            List <int> filterAttributeIds = null;
            var        filterAttributeKey = GetAttributeValue("GroupMemberAttributeFilter");

            if (!string.IsNullOrWhiteSpace(filterAttributeKey))
            {
                filterAttributeIds = attributeService.Queryable()
                                     .Where(a =>
                                            (groupIdStrings.Contains(a.EntityTypeQualifierValue) || groupTypeIds.Contains(a.EntityTypeQualifierValue)) &&
                                            a.Key == filterAttributeKey &&
                                            a.EntityTypeId == groupEntityid)
                                     .Select(a => a.Id).ToList();
            }

            var attributeMatrixItemEntityId = EntityTypeCache.GetId <AttributeMatrixItem>();

            AttributeValueService      attributeValueService      = new AttributeValueService(rockContext);
            AttributeMatrixService     attributeMatrixService     = new AttributeMatrixService(rockContext);
            AttributeMatrixItemService attributeMatrixItemService = new AttributeMatrixItemService(rockContext);
            HistoryService             historyService             = new HistoryService(rockContext);

            var qry = new GroupMemberService(rockContext).Queryable()
                      .Join(
                attributeValueService.Queryable().Where(av => attributeIds.Contains(av.AttributeId)),
                m => m.Id,
                av => av.EntityId.Value,
                (m, av) => new { Member = m, AttributeValue = av.Value }
                )
                      .Join(
                attributeMatrixService.Queryable(),
                m => m.AttributeValue,
                am => am.Guid.ToString(),
                (m, am) => new { Member = m.Member, AttributeMatrix = am }
                )
                      .Join(
                attributeMatrixItemService.Queryable(),
                m => m.AttributeMatrix.Id,
                ami => ami.AttributeMatrixId,
                (m, ami) => new { Member = m.Member, AttributeMatrixItem = ami, TemplateId = ami.AttributeMatrix.AttributeMatrixTemplateId }
                )
                      .Join(
                attributeService.Queryable(),
                m => new { TemplateIdString = m.TemplateId.ToString(), EntityTypeId = attributeMatrixItemEntityId },
                a => new { TemplateIdString = a.EntityTypeQualifierValue, EntityTypeId = a.EntityTypeId },
                (m, a) => new { Member = m.Member, AttributeMatrixItem = m.AttributeMatrixItem, Attribute = a }
                )
                      .Join(
                attributeValueService.Queryable(),
                m => new { EntityId = m.AttributeMatrixItem.Id, AttributeId = m.Attribute.Id },
                av => new { EntityId = av.EntityId ?? 0, AttributeId = av.AttributeId },
                (m, av) => new { Member = m.Member, Attribute = m.Attribute, AttributeValue = av, MatrixItemId = m.AttributeMatrixItem.Id, FilterValue = "" }
                ).
                      Where(obj => groupIds.Contains(obj.Member.GroupId));

            if (filterAttributeIds != null && pnlAttribute.Visible && !string.IsNullOrWhiteSpace(ddlAttribute.SelectedValue))
            {
                var filterValue = ddlAttribute.SelectedValue;
                qry = qry
                      .Join(
                    attributeValueService.Queryable().Where(av => filterAttributeIds.Contains(av.AttributeId)),
                    m => new { Id = m.Member.Id, Value = filterValue },
                    av => new { Id = av.EntityId ?? 0, Value = av.Value },
                    (m, av) => new { Member = m.Member, Attribute = m.Attribute, AttributeValue = m.AttributeValue, MatrixItemId = m.MatrixItemId, FilterValue = av.Value });
            }
            var members = qry.ToList().GroupBy(a => a.Member).ToList();

            var firstDay = (dpDate.SelectedDate ?? Rock.RockDateTime.Today).Date;
            var nextday  = firstDay.AddDays(1);

            var personIds = members.Select(m => m.Key.PersonId);
            var attributeMatrixEntityTypeId = EntityTypeCache.GetId <AttributeMatrixItem>().Value;

            var historyItems = historyService.Queryable()
                               .Where(h => personIds.Contains(h.EntityId))
                               .Where(h => h.RelatedEntityTypeId == attributeMatrixEntityTypeId)
                               .Where(h => h.CreatedDateTime >= firstDay && h.CreatedDateTime < nextday)
                               .ToList();

            foreach (var member in members)
            {
                if (!string.IsNullOrWhiteSpace(tbName.Text) &&
                    !member.Key.Person.FullName.ToLower().Contains(tbName.Text.ToLower()) &&
                    !member.Key.Person.FullNameReversed.ToLower().Contains(tbName.Text.ToLower()))
                {
                    continue;
                }

                var medicines = member.GroupBy(m => m.MatrixItemId);
                foreach (var medicine in medicines)
                {
                    var scheduleAtt = medicine.FirstOrDefault(m => m.Attribute.Key == "Schedule");
                    var schedules   = scheduleAtt.AttributeValue.Value.SplitDelimitedValues();
                    foreach (var schedule in schedules)
                    {
                        if (ddlSchedule.SelectedValue != "" && ddlSchedule.SelectedValue.AsGuid() != schedule.AsGuid())
                        {
                            continue;
                        }

                        var medicalItem = new MedicalItem()
                        {
                            Person          = member.Key.Person.FullNameReversed,
                            GroupMemberId   = member.Key.Id,
                            GroupMember     = member.FirstOrDefault().Member,
                            PersonId        = member.Key.Person.Id,
                            FilterAttribute = member.FirstOrDefault().FilterValue
                        };

                        if (!string.IsNullOrWhiteSpace(schedule))
                        {
                            var dv = DefinedValueCache.Read(schedule.AsGuid());
                            if (dv != null)
                            {
                                medicalItem.Schedule     = dv.Value;
                                medicalItem.ScheduleGuid = dv.Guid;
                            }
                        }

                        var medAtt = medicine.FirstOrDefault(m => m.Attribute.Key == "Medication");
                        if (medAtt != null)
                        {
                            medicalItem.Medication = medAtt.AttributeValue.Value;
                        }

                        var instructionAtt = medicine.FirstOrDefault(m => m.Attribute.Key == "Instructions");
                        if (instructionAtt != null)
                        {
                            medicalItem.Instructions = instructionAtt.AttributeValue.Value;
                        }
                        medicalItem.Key = string.Format("{0}|{1}|{2}", medicalItem.PersonId, medicine.Key, medicalItem.ScheduleGuid);

                        var history = historyItems.Where(h => h.EntityId == medicalItem.PersonId && h.RelatedEntityId == medicine.Key && (string.IsNullOrWhiteSpace(h.RelatedData) || h.RelatedData.AsGuid() == medicalItem.ScheduleGuid));
                        if (history.Any())
                        {
                            medicalItem.Distributed = true;
                            medicalItem.History     = string.Join("<br>", history.Select(h => h.Summary));
                        }
                        medicalItems.Add(medicalItem);
                    }
                }
            }

            SortProperty sortProperty = gGrid.SortProperty;

            if (sortProperty != null)
            {
                if (sortProperty.Property == "Person")
                {
                    if (sortProperty.Direction == SortDirection.Ascending)
                    {
                        medicalItems = medicalItems.OrderBy(mi => mi.Person).ToList();
                    }
                    else
                    {
                        medicalItems = medicalItems.OrderByDescending(mi => mi.Person).ToList();
                    }
                }
            }
            else
            {
                medicalItems       = medicalItems.OrderBy(mi => mi.Person).ToList();
                gGrid.SortProperty = new SortProperty()
                {
                    Property = "Person"
                };
            }

            return(medicalItems);
        }
Example #2
0
        /// <summary>
        /// Gets the merge object list for the current EntitySet
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="fetchCount">The fetch count.</param>
        /// <returns></returns>
        private List <object> GetMergeObjectList(RockContext rockContext, int?fetchCount = null)
        {
            int entitySetId      = hfEntitySetId.Value.AsInteger();
            var entitySetService = new EntitySetService(rockContext);
            var entitySet        = entitySetService.Get(entitySetId);
            Dictionary <int, object> mergeObjectsDictionary = new Dictionary <int, object>();

            // If this EntitySet contains IEntity Items, add those first
            if (entitySet.EntityTypeId.HasValue)
            {
                var qryEntity = entitySetService.GetEntityQuery(entitySetId);

                if (fetchCount.HasValue)
                {
                    qryEntity = qryEntity.Take(fetchCount.Value);
                }

                var  entityTypeCache         = EntityTypeCache.Read(entitySet.EntityTypeId.Value);
                bool isPersonEntityType      = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.PERSON.AsGuid();
                bool isGroupMemberEntityType = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.GROUP_MEMBER.AsGuid();
                bool combineFamilyMembers    = cbCombineFamilyMembers.Visible && cbCombineFamilyMembers.Checked;

                if ((isGroupMemberEntityType || isPersonEntityType) && combineFamilyMembers)
                {
                    IQueryable <IEntity> qryPersons;
                    if (isGroupMemberEntityType)
                    {
                        qryPersons = qryEntity.OfType <GroupMember>().Select(a => a.Person).Distinct();
                    }
                    else
                    {
                        qryPersons = qryEntity;
                    }

                    Guid familyGroupType       = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid();
                    var  qryFamilyGroupMembers = new GroupMemberService(rockContext).Queryable("GroupRole,Person").AsNoTracking()
                                                 .Where(a => a.Group.GroupType.Guid == familyGroupType)
                                                 .Where(a => qryPersons.Any(aa => aa.Id == a.PersonId));

                    var qryCombined = qryFamilyGroupMembers.Join(
                        qryPersons,
                        m => m.PersonId,
                        p => p.Id,
                        (m, p) => new { GroupMember = m, Person = p })
                                      .GroupBy(a => a.GroupMember.GroupId)
                                      .Select(x => new
                    {
                        GroupId = x.Key,
                        // Order People to match ordering in the GroupMembers.ascx block.
                        Persons =
                            // Adult Male
                            x.Where(xx => xx.GroupMember.GroupRole.Guid.Equals(new Guid(Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT)) &&
                                    xx.GroupMember.Person.Gender == Gender.Male).OrderByDescending(xx => xx.GroupMember.Person.BirthDate).Select(xx => xx.Person)
                            // Adult Female
                            .Concat(x.Where(xx => xx.GroupMember.GroupRole.Guid.Equals(new Guid(Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT)) &&
                                            xx.GroupMember.Person.Gender != Gender.Male).OrderByDescending(xx => xx.GroupMember.Person.BirthDate).Select(xx => xx.Person))
                            // non-adults
                            .Concat(x.Where(xx => !xx.GroupMember.GroupRole.Guid.Equals(new Guid(Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT)))
                                    .OrderByDescending(xx => xx.GroupMember.Person.BirthDate).Select(xx => xx.Person))
                    });

                    foreach (var combinedFamilyItem in qryCombined)
                    {
                        object mergeObject;

                        string commaPersonIds = combinedFamilyItem.Persons.Select(a => a.Id).Distinct().ToList().AsDelimited(",");

                        var primaryGroupPerson = combinedFamilyItem.Persons.FirstOrDefault() as Person;

                        if (mergeObjectsDictionary.ContainsKey(primaryGroupPerson.Id))
                        {
                            foreach (var person in combinedFamilyItem.Persons)
                            {
                                if (!mergeObjectsDictionary.ContainsKey(person.Id))
                                {
                                    primaryGroupPerson = person as Person;
                                    break;
                                }
                            }
                        }

                        // if we are combining from a GroupMemberEntityType list add the GroupMember attributes of the primary person in the combined list
                        if (isGroupMemberEntityType)
                        {
                            var groupMember = qryEntity.OfType <GroupMember>().Where(a => a.PersonId == primaryGroupPerson.Id).FirstOrDefault();
                            primaryGroupPerson.AdditionalLavaFields = primaryGroupPerson.AdditionalLavaFields ?? new Dictionary <string, object>();
                            if (groupMember != null)
                            {
                                primaryGroupPerson.AdditionalLavaFields.AddOrIgnore("GroupMember", groupMember);
                            }
                        }

                        if (combinedFamilyItem.Persons.Count() > 1)
                        {
                            var combinedPerson = primaryGroupPerson.ToJson().FromJsonOrNull <MergeTemplateCombinedPerson>();

                            var familyTitle = RockUdfHelper.ufnCrm_GetFamilyTitle(rockContext, null, combinedFamilyItem.GroupId, commaPersonIds, true);
                            combinedPerson.FullName = familyTitle;

                            var firstNameList = combinedFamilyItem.Persons.Select(a => (a as Person).FirstName).ToList();
                            var nickNameList  = combinedFamilyItem.Persons.Select(a => (a as Person).NickName).ToList();

                            combinedPerson.FirstName     = firstNameList.AsDelimited(", ", " & ");
                            combinedPerson.NickName      = nickNameList.AsDelimited(", ", " & ");
                            combinedPerson.LastName      = primaryGroupPerson.LastName;
                            combinedPerson.SuffixValueId = null;
                            combinedPerson.SuffixValue   = null;
                            mergeObject = combinedPerson;
                        }
                        else
                        {
                            mergeObject = primaryGroupPerson;
                        }

                        mergeObjectsDictionary.AddOrIgnore(primaryGroupPerson.Id, mergeObject);
                    }
                }
                else if (isGroupMemberEntityType)
                {
                    foreach (var groupMember in qryEntity.AsNoTracking().OfType <GroupMember>())
                    {
                        var person = groupMember.Person;
                        person.AdditionalLavaFields = new Dictionary <string, object>();
                        person.AdditionalLavaFields.Add("GroupMember", groupMember);
                        mergeObjectsDictionary.AddOrIgnore(groupMember.PersonId, person);
                    }
                }
                else
                {
                    foreach (var item in qryEntity.AsNoTracking())
                    {
                        mergeObjectsDictionary.AddOrIgnore(item.Id, item);
                    }
                }
            }

            var entitySetItemService = new EntitySetItemService(rockContext);

            string[] emptyJson = new string[] { string.Empty, "{}" };
            var      entitySetItemMergeValuesQry = entitySetItemService.GetByEntitySetId(entitySetId, true).Where(a => !emptyJson.Contains(a.AdditionalMergeValuesJson));

            if (fetchCount.HasValue)
            {
                entitySetItemMergeValuesQry = entitySetItemMergeValuesQry.Take(fetchCount.Value);
            }

            // the entityId to use for NonEntity objects
            int nonEntityId = 1;

            // now, add the additional MergeValues regardless of if the EntitySet contains IEntity items or just Non-IEntity items
            foreach (var additionalMergeValuesItem in entitySetItemMergeValuesQry.AsNoTracking())
            {
                object mergeObject;
                int    entityId;
                if (additionalMergeValuesItem.EntityId > 0)
                {
                    entityId = additionalMergeValuesItem.EntityId;
                }
                else
                {
                    // not pointing to an actual EntityId, so use the nonEntityId for ti
                    entityId = nonEntityId++;
                }

                if (mergeObjectsDictionary.ContainsKey(entityId))
                {
                    mergeObject = mergeObjectsDictionary[entityId];
                }
                else
                {
                    if (entitySet.EntityTypeId.HasValue)
                    {
                        // if already have real entities in our list, don't add additional items to the mergeObjectsDictionary
                        continue;
                    }

                    // non-Entity merge object, so just use Dictionary
                    mergeObject = new Dictionary <string, object>();
                    mergeObjectsDictionary.AddOrIgnore(entityId, mergeObject);
                }

                foreach (var additionalMergeValue in additionalMergeValuesItem.AdditionalMergeValues)
                {
                    if (mergeObject is IEntity)
                    {
                        // add the additional fields to AdditionalLavaFields
                        IEntity mergeEntity = (mergeObject as IEntity);
                        mergeEntity.AdditionalLavaFields = mergeEntity.AdditionalLavaFields ?? new Dictionary <string, object>();
                        object mergeValueObject = additionalMergeValue.Value;

                        // if the mergeValueObject is a JArray (JSON Object), convert it into an ExpandoObject or List<ExpandoObject> so that Lava will work on it
                        if (mergeValueObject is JArray)
                        {
                            var jsonOfObject = mergeValueObject.ToJson();
                            try
                            {
                                mergeValueObject = Rock.Lava.RockFilters.FromJSON(jsonOfObject);
                            }
                            catch (Exception ex)
                            {
                                LogException(new Exception("MergeTemplateEntry couldn't do a FromJSON", ex));
                            }
                        }

                        mergeEntity.AdditionalLavaFields.AddOrIgnore(additionalMergeValue.Key, mergeValueObject);
                    }
                    else if (mergeObject is IDictionary <string, object> )
                    {
                        // anonymous object with no fields yet
                        IDictionary <string, object> nonEntityObject = mergeObject as IDictionary <string, object>;
                        nonEntityObject.AddOrIgnore(additionalMergeValue.Key, additionalMergeValue.Value);
                    }
                    else
                    {
                        throw new Exception(string.Format("Unexpected MergeObject Type: {0}", mergeObject));
                    }
                }
            }

            var result = mergeObjectsDictionary.Select(a => a.Value);

            if (fetchCount.HasValue)
            {
                // make sure the result is limited to fetchCount (even though the above queries are also limited to fetch count)
                result = result.Take(fetchCount.Value);
            }

            return(result.ToList());
        }
        /// <summary>
        /// Gets the merge object list for the current EntitySet
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="fetchCount">The fetch count.</param>
        /// <returns></returns>
        private List <object> GetMergeObjectList(RockContext rockContext, int?fetchCount = null)
        {
            int entitySetId      = hfEntitySetId.Value.AsInteger();
            var entitySetService = new EntitySetService(rockContext);
            var entitySet        = entitySetService.Get(entitySetId);
            Dictionary <int, object> mergeObjectsDictionary = new Dictionary <int, object>();

            // If this EntitySet contains IEntity Items, add those first
            if (entitySet.EntityTypeId.HasValue)
            {
                var qryEntity = entitySetService.GetEntityQuery(entitySetId);

                if (fetchCount.HasValue)
                {
                    qryEntity = qryEntity.Take(fetchCount.Value);
                }

                var  entityTypeCache         = EntityTypeCache.Read(entitySet.EntityTypeId.Value);
                bool isPersonEntityType      = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.PERSON.AsGuid();
                bool isGroupMemberEntityType = entityTypeCache != null && entityTypeCache.Guid == Rock.SystemGuid.EntityType.GROUP_MEMBER.AsGuid();
                bool combineFamilyMembers    = cbCombineFamilyMembers.Visible && cbCombineFamilyMembers.Checked;

                if (isPersonEntityType && combineFamilyMembers)
                {
                    var  qryPersons            = qryEntity;
                    Guid familyGroupType       = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid();
                    var  qryFamilyGroupMembers = new GroupMemberService(rockContext).Queryable()
                                                 .Where(a => a.Group.GroupType.Guid == familyGroupType)
                                                 .Where(a => qryPersons.Any(aa => aa.Id == a.PersonId));

                    var qryCombined = qryFamilyGroupMembers.Join(
                        qryPersons,
                        m => m.PersonId,
                        p => p.Id,
                        (m, p) => new { GroupMember = m, Person = p })
                                      .GroupBy(a => a.GroupMember.GroupId)
                                      .Select(x => new
                    {
                        GroupId = x.Key,
                        Persons = x.Select(xx => xx.Person).Distinct()
                    });

                    foreach (var combinedFamilyItem in qryCombined)
                    {
                        object mergeObject;

                        string commaPersonIds = combinedFamilyItem.Persons.Select(a => a.Id).Distinct().ToList().AsDelimited(",");

                        var primaryGroupPerson = combinedFamilyItem.Persons.FirstOrDefault() as Person;

                        if (mergeObjectsDictionary.ContainsKey(primaryGroupPerson.Id))
                        {
                            foreach (var person in combinedFamilyItem.Persons)
                            {
                                if (!mergeObjectsDictionary.ContainsKey(person.Id))
                                {
                                    primaryGroupPerson = person as Person;
                                    break;
                                }
                            }
                        }

                        if (combinedFamilyItem.Persons.Count() > 1)
                        {
                            var combinedPerson = primaryGroupPerson.ToJson().FromJsonOrNull <MergeTemplateCombinedPerson>();

                            var familyTitle = RockUdfHelper.ufnCrm_GetFamilyTitle(rockContext, null, combinedFamilyItem.GroupId, commaPersonIds, true);
                            combinedPerson.FullName = familyTitle;

                            var firstNameList = combinedFamilyItem.Persons.Select(a => (a as Person).FirstName).ToList();
                            var nickNameList  = combinedFamilyItem.Persons.Select(a => (a as Person).NickName).ToList();

                            combinedPerson.FirstName     = firstNameList.AsDelimited(", ", " & ");
                            combinedPerson.NickName      = nickNameList.AsDelimited(", ", " & ");
                            combinedPerson.LastName      = primaryGroupPerson.LastName;
                            combinedPerson.SuffixValueId = null;
                            combinedPerson.SuffixValue   = null;
                            mergeObject = combinedPerson;
                        }
                        else
                        {
                            mergeObject = primaryGroupPerson;
                        }

                        mergeObjectsDictionary.AddOrIgnore(primaryGroupPerson.Id, mergeObject);
                    }
                }
                else if (isGroupMemberEntityType)
                {
                    foreach (var groupMember in qryEntity.AsNoTracking().OfType <GroupMember>())
                    {
                        var person = groupMember.Person;
                        person.AdditionalLavaFields = new Dictionary <string, object>();

                        foreach (var item in groupMember.ToDictionary())
                        {
                            if (item.Key == "Id")
                            {
                                person.AdditionalLavaFields.AddOrIgnore("GroupMemberId", item.Value);
                            }
                            else if (item.Key == "Guid")
                            {
                                person.AdditionalLavaFields.AddOrIgnore("GroupMemberGuid", item.Value.ToStringSafe());
                            }
                            else
                            {
                                person.AdditionalLavaFields.AddOrIgnore(item.Key, item.Value);
                            }
                        }

                        mergeObjectsDictionary.AddOrIgnore(groupMember.PersonId, person);
                    }
                }
                else
                {
                    foreach (var item in qryEntity.AsNoTracking())
                    {
                        mergeObjectsDictionary.AddOrIgnore(item.Id, item);
                    }
                }
            }

            var entitySetItemService = new EntitySetItemService(rockContext);

            string[] emptyJson = new string[] { string.Empty, "{}" };
            var      entitySetItemMergeValuesQry = entitySetItemService.GetByEntitySetId(entitySetId, true).Where(a => !emptyJson.Contains(a.AdditionalMergeValuesJson));

            if (fetchCount.HasValue)
            {
                entitySetItemMergeValuesQry = entitySetItemMergeValuesQry.Take(fetchCount.Value);
            }

            // the entityId to use for NonEntity objects
            int nonEntityId = 1;

            // now, add the additional MergeValues regardless of if the EntitySet contains IEntity items or just Non-IEntity items
            foreach (var additionalMergeValuesItem in entitySetItemMergeValuesQry.AsNoTracking())
            {
                object mergeObject;
                int    entityId;
                if (additionalMergeValuesItem.EntityId > 0)
                {
                    entityId = additionalMergeValuesItem.EntityId;
                }
                else
                {
                    // not pointing to an actual EntityId, so use the nonEntityId for ti
                    entityId = nonEntityId++;
                }

                if (mergeObjectsDictionary.ContainsKey(entityId))
                {
                    mergeObject = mergeObjectsDictionary[entityId];
                }
                else
                {
                    if (entitySet.EntityTypeId.HasValue)
                    {
                        // if already have real entities in our list, don't add additional items to the mergeObjectsDictionary
                        continue;
                    }

                    // non-Entity merge object, so just use Dictionary
                    mergeObject = new Dictionary <string, object>();
                    mergeObjectsDictionary.AddOrIgnore(entityId, mergeObject);
                }

                foreach (var additionalMergeValue in additionalMergeValuesItem.AdditionalMergeValues)
                {
                    if (mergeObject is IEntity)
                    {
                        // add the additional fields to AdditionalLavaFields
                        IEntity mergeEntity = (mergeObject as IEntity);
                        mergeEntity.AdditionalLavaFields = mergeEntity.AdditionalLavaFields ?? new Dictionary <string, object>();
                        object mergeValueObject = additionalMergeValue.Value;
                        mergeEntity.AdditionalLavaFields.AddOrIgnore(additionalMergeValue.Key, mergeValueObject);
                    }
                    else if (mergeObject is IDictionary <string, object> )
                    {
                        // anonymous object with no fields yet
                        IDictionary <string, object> nonEntityObject = mergeObject as IDictionary <string, object>;
                        nonEntityObject.AddOrIgnore(additionalMergeValue.Key, additionalMergeValue.Value);
                    }
                    else
                    {
                        throw new Exception(string.Format("Unexpected MergeObject Type: {0}", mergeObject));
                    }
                }
            }

            var result = mergeObjectsDictionary.Select(a => a.Value);

            if (fetchCount.HasValue)
            {
                // make sure the result is limited to fetchCount (even though the above queries are also limited to fetch count)
                result = result.Take(fetchCount.Value);
            }

            return(result.ToList());
        }