private IEnumerable<EntityInstanceVm> Level3(Entity matchEntity, EntityInstance matchEntityInstance, int skip, int limit)
        {

            var entityMatchNode = matchEntity.MatchNode("entity");
            var entityInstanceMatchNode = matchEntityInstance == null ? new EntityInstance().NodeNameWithAlias("entityInstance") : matchEntityInstance.MatchNode("entityInstance");

            var query = StagedDbContext.Instance.GraphClient.Cypher
                .Match(string.Format("{0}<-[:INSTANCE_OF]-{1}", entityMatchNode, entityInstanceMatchNode))
                .With("entityInstance, entity, count(entityInstance) AS totalCount")
                .Skip(skip)
                .Limit(limit)
                .Match("(property:Property)<-[:HAS_PROPERTY]-(entity)")
                .With("entityInstance, entity, property, totalCount")

                .OptionalMatch("(property)-[:FOR_ENTITY]->(entityPropertyEntity:Entity)")
                .OptionalMatch("(entityInstance)-[:HAS_PROPERTY_VALUE]->(dataPropertyPropertyValue:PropertyValue)-[:IS_VALUE_FOR_PROPERTY]->(property)")
                .OptionalMatch("(entityInstance)-[:HAS_PROPERTY_VALUE]->(entityPropertyEntityInstance:EntityInstance)-[:IS_VALUE_FOR_PROPERTY]->(property)-[:FOR_ENTITY]->(entityPropertyEntity)")

                .OptionalMatch("(property2:Property)<-[:HAS_PROPERTY]-(entityPropertyEntity)<-[:INSTANCE_OF]-(entityPropertyEntityInstance)")

                .OptionalMatch("(property2)-[:FOR_ENTITY]->(entityPropertyEntity2:Entity)")
                .OptionalMatch("(entityPropertyEntityInstance)-[:HAS_PROPERTY_VALUE]->(dataPropertyPropertyValue2:PropertyValue)-[:IS_VALUE_FOR_PROPERTY]->(property2)")
                .OptionalMatch("(entityPropertyEntityInstance)-[:HAS_PROPERTY_VALUE]->(entityPropertyEntityInstance2:EntityInstance)-[:IS_VALUE_FOR_PROPERTY]->(property2)-[:FOR_ENTITY]->(entityPropertyEntity2)")

                .OptionalMatch("(property3:Property)<-[:HAS_PROPERTY]-(entityPropertyEntity2)<-[:INSTANCE_OF]-(entityPropertyEntityInstance2)")

                .OptionalMatch("(property3)-[:FOR_ENTITY]->(entityPropertyEntity3:Entity)")
                .OptionalMatch("(entityPropertyEntityInstance2)-[:HAS_PROPERTY_VALUE]->(dataPropertyPropertyValue3:PropertyValue)-[:IS_VALUE_FOR_PROPERTY]->(property3)")
                .OptionalMatch("(entityPropertyEntityInstance2)-[:HAS_PROPERTY_VALUE]->(entityPropertyEntityInstance3:EntityInstance)-[:IS_VALUE_FOR_PROPERTY]->(property3)-[:FOR_ENTITY]->(entityPropertyEntity3)")


                .Return((entity, entityInstance, 
                property, dataPropertyPropertyValue, entityPropertyEntityInstance, entityPropertyEntity,
                property2, dataPropertyPropertyValue2, entityPropertyEntityInstance2, entityPropertyEntity2,
                property3, dataPropertyPropertyValue3, entityPropertyEntityInstance3, entityPropertyEntity3) => new
                {

                    //first
                    entity = (entity.As<Entity>()),
                    entityInstance = entityInstance.As<EntityInstance>(),
                    entityPropertyEntityInstance = entityPropertyEntityInstance.As<EntityInstance>(),
                    dataPropertyPropertyValue = dataPropertyPropertyValue.As<PropertyValue>(),
                    property = property.As<Property>(),

                    entityPropertyEntity = entityPropertyEntity.As<Entity>(),

                    property2 = property2.As<Property>(),
                    dataPropertyPropertyValue2 = dataPropertyPropertyValue2.As<PropertyValue>(),
                    entityPropertyEntityInstance2 = entityPropertyEntityInstance2.As<EntityInstance>(),

                    entityPropertyEntity2 = entityPropertyEntity2.As<Entity>(),

                    property3 = property3.As<Property>(),
                    dataPropertyPropertyValue3 = dataPropertyPropertyValue3.As<PropertyValue>(),
                    entityPropertyEntityInstance3 = entityPropertyEntityInstance3.As<EntityInstance>(),

                    entityPropertyEntity3 = entityPropertyEntity3.As<Entity>(),
                });



            var results = query.Results
                .GroupBy(x =>
                    new
                    {
                        entityInstanceGuid = x.entityInstance.guid,
                        entityName = x.entity.name,
                        entityGuid = x.entity.guid,
                    }
                )
                .Select(y => new
                    //asset
                    EntityInstanceVm
                {
                    guid = y.Key.entityInstanceGuid,
                    entity = new PartialEntityVm { name = y.Key.entityName, guid = y.Key.entityGuid },
                    dataProperties = y.Where(ww => ww.property.dataType != DataTypeEnum.EntityInstance)
                    .GroupBy(az => new
                    {
                        propertyGuid = az.property.guid,
                        propertyName = az.property.name,
                    })
                    .Select(bz => new DataPropertyInstanceVm
                    {
                        guid = bz.Key.propertyGuid,
                        name = bz.Key.propertyName,
                        value = bz.First().dataPropertyPropertyValue == null ? null : bz.First().dataPropertyPropertyValue.value
                    }),
                    entityProperties = y.Where(www => www.property.dataType == DataTypeEnum.EntityInstance)
                    .GroupBy(z =>
                        new
                        {
                            propertyGuid = z.property.guid,
                            propertyName = z.property.name,
                            entityPropertyEntityName = z.entityPropertyEntity.name,
                            entityPropertyEntityGuid = z.entityPropertyEntity.guid,
                        }
                    )
                    .Select(entityInstanceProperties =>
                        new EntityPropertyInstanceVm
                        {
                            guid = entityInstanceProperties.Key.propertyGuid,
                            name = entityInstanceProperties.Key.propertyName,
                            //asset type
                            entity = new PartialEntityVm { guid = entityInstanceProperties.Key.entityPropertyEntityGuid, name = entityInstanceProperties.Key.entityPropertyEntityName },
                            entityInstanceGuid = entityInstanceProperties.First().entityPropertyEntityInstance == null ? null : entityInstanceProperties.First().entityPropertyEntityInstance.guid,
                            entityInstance = entityInstanceProperties.First().entityPropertyEntityInstance == null ? null : new EntityInstanceVm
                            {
                                guid = entityInstanceProperties.First().entityPropertyEntityInstance == null ? null : entityInstanceProperties.First().entityPropertyEntityInstance.guid,
                                entity = new PartialEntityVm { guid = entityInstanceProperties.Key.entityPropertyEntityGuid, name = entityInstanceProperties.Key.entityPropertyEntityName },
                                dataProperties = entityInstanceProperties.Where(ww => ww.property2 != null && ww.property2.dataType != DataTypeEnum.EntityInstance)
                                .GroupBy(az => new
                                {
                                    propertyGuid = az.property2.guid,
                                    propertyName = az.property2.name,
                                })
                                .Select(oz => new DataPropertyInstanceVm
                                {
                                    guid = oz.Key.propertyGuid,
                                    name = oz.Key.propertyName,
                                    value = oz.First().dataPropertyPropertyValue2 == null ? null : oz.First().dataPropertyPropertyValue2.value
                                }),
                                entityProperties = entityInstanceProperties.Where(ww => ww.property2 != null && ww.property2.dataType == DataTypeEnum.EntityInstance)
                                .GroupBy(pz => new
                                {
                                    propertyGuid = pz.property2.guid,
                                    propertyName = pz.property2.name,
                                    entityPropertyEntityName = pz.entityPropertyEntity2.name,
                                    entityPropertyEntityGuid = pz.entityPropertyEntity2.guid,
                                })
                                .Select(entityInstanceProperties2 => new EntityPropertyInstanceVm
                                {
                                    guid = entityInstanceProperties2.Key.propertyGuid,
                                    name = entityInstanceProperties2.Key.propertyName,
                                    entity = new PartialEntityVm { guid = entityInstanceProperties2.Key.entityPropertyEntityGuid, name = entityInstanceProperties2.Key.entityPropertyEntityName },
                                    entityInstanceGuid = entityInstanceProperties2.First().entityPropertyEntityInstance2 == null ? null : entityInstanceProperties2.First().entityPropertyEntityInstance2.guid,
                                    entityInstance = entityInstanceProperties2.First().entityPropertyEntityInstance == null ? null : new EntityInstanceVm
                                    {
                                        guid = entityInstanceProperties2.First().entityPropertyEntityInstance == null ? null : entityInstanceProperties2.First().entityPropertyEntityInstance.guid,
                                        entity = new PartialEntityVm { guid = entityInstanceProperties2.Key.entityPropertyEntityGuid, name = entityInstanceProperties2.Key.entityPropertyEntityName },
                                        dataProperties = entityInstanceProperties2.Where(ww => ww.property3 != null && ww.property3.dataType != DataTypeEnum.EntityInstance)
                                        .GroupBy(az => new
                                        {
                                            propertyGuid = az.property3.guid,
                                            propertyName = az.property3.name,
                                        })
                                        .Select(oz => new DataPropertyInstanceVm
                                        {
                                            guid = oz.Key.propertyGuid,
                                            name = oz.Key.propertyName,
                                            value = oz.First().dataPropertyPropertyValue3 == null ? null : oz.First().dataPropertyPropertyValue3.value
                                        }),
                                        entityProperties = entityInstanceProperties2.Where(ww => ww.property3 != null && ww.property3.dataType == DataTypeEnum.EntityInstance)
                                        .GroupBy(pz => new
                                        {
                                            propertyGuid = pz.property3.guid,
                                            propertyName = pz.property3.name,
                                            entityPropertyEntityName = pz.entityPropertyEntity3.name,
                                            entityPropertyEntityGuid = pz.entityPropertyEntity3.guid,
                                        })
                                        .Select(pp => new EntityPropertyInstanceVm
                                        {
                                            guid = pp.Key.propertyGuid,
                                            name = pp.Key.propertyName,
                                            entity = new PartialEntityVm { guid = pp.Key.entityPropertyEntityGuid, name = pp.Key.entityPropertyEntityName },
                                            entityInstanceGuid = pp.First().entityPropertyEntityInstance3 == null ? null : pp.First().entityPropertyEntityInstance3.guid,
                                        }),

                                    }
                                }),

                            }
                        }
                    )

                }).ToList();

            var all = results.SelectMany(m => m.entityProperties, (parent, child) => child.entityInstance)
                .Union(results.Select(p => new EntityInstanceVm
                {
                    guid = p.guid,
                    entity = p.entity,
                    entityProperties = p.entityProperties,
                    dataProperties = p.dataProperties

                }))
                .Where(g => g != null)
                .GroupBy(by => by.guid)
                .Select(group => group.First())
                .Union(
                    results.SelectMany(m => m.entityProperties, (parent, child) => child.entityInstance)
                    .Where(g => g != null)
                    .SelectMany(m => m.entityProperties, (parent, child) => child.entityInstance)
                    .GroupBy(by => by.guid)
                    .Select(group => group.First())
                )
                ;

            return all;
        }
        private IEnumerable<EntityInstanceVm> Level1(Entity matchEntity, EntityInstance matchEntityInstance, int skip, int limit)
        {

            var entityMatchNode = matchEntity.MatchNode("entity");
            var entityInstanceMatchNode = matchEntityInstance == null ? new EntityInstance().NodeNameWithAlias("entityInstance") : matchEntityInstance.MatchNode("entityInstance");

            var query = StagedDbContext.Instance.GraphClient.Cypher
                .Match(string.Format("{0}<-[:INSTANCE_OF]-{1}", entityMatchNode, entityInstanceMatchNode))
                .With("entityInstance, entity, count(entityInstance) AS totalCount")
                .Skip(skip)
                .Limit(limit)
                .Match("(property:Property)<-[:HAS_PROPERTY]-(entity)")
                .With("entityInstance, entity, property, totalCount")
                .OptionalMatch("(property)-[:FOR_ENTITY]->(entityPropertyEntity:Entity)")
                .OptionalMatch("(entityInstance)-[:HAS_PROPERTY_VALUE]->(dataPropertyPropertyValue:PropertyValue)-[:IS_VALUE_FOR_PROPERTY]->(property)")
                .OptionalMatch("(entityInstance)-[:HAS_PROPERTY_VALUE]->(entityPropertyEntityInstance:EntityInstance)-[:IS_VALUE_FOR_PROPERTY]->(property)-[:FOR_ENTITY]->(entityPropertyEntity)")
                .Return((entity, entityInstance, property, entityPropertyEntity, dataPropertyPropertyValue, entityPropertyEntityInstance, totalCount) => new
                {

                    //for each entity asset
                    entity = (entity.As<Entity>()),
                    entityInstance = entityInstance.As<EntityInstance>(),

                    //for each property asset type
                    entityPropertyEntityInstance = entityPropertyEntityInstance.As<EntityInstance>(),
                    entityPropertyEntity = entityPropertyEntity.As<Entity>(),
                    dataPropertyPropertyValue = dataPropertyPropertyValue.As<PropertyValue>(),
                    property = property.As<Property>(),
                    totalCount = totalCount.As<int>()
                });



            var results = query.Results
                .GroupBy(x =>
                    new
                    {
                        entityInstanceGuid = x.entityInstance.guid,
                        entityName = x.entity.name,
                        entityGuid = x.entity.guid,
                    }
                )
                .Select(y => new
                    //asset
                    EntityInstanceVm
                {
                    guid = y.Key.entityInstanceGuid,
                    entity = new PartialEntityVm { name = y.Key.entityName, guid = y.Key.entityGuid },
                    dataProperties = y.GroupBy(az => new { 
                        propertyValue = az.dataPropertyPropertyValue,
                        dataProperty = az.property
                    })
                    .Where(ww => ww.Key.dataProperty.dataType != DataTypeEnum.EntityInstance)
                    .Select(bz => new DataPropertyInstanceVm { 
                        guid = bz.Key.dataProperty.guid,
                        name = bz.Key.dataProperty.name,
                        value = bz.Key.propertyValue == null ? null : bz.Key.propertyValue.value 
                    }),
                    entityProperties = y
                    .GroupBy(z =>
                        new
                        {
                            entityProperty = z.property,
                            entityInstance = z.entityPropertyEntityInstance,
                            entityInstanceEntity = z.entityPropertyEntity,

                        }
                    )
                    .Where(www => www.Key.entityProperty.dataType == DataTypeEnum.EntityInstance)
                    .Select(entityInstanceProperties =>
                        new EntityPropertyInstanceVm
                        {
                            guid = entityInstanceProperties.Key.entityProperty.guid,
                            name = entityInstanceProperties.Key.entityProperty.name,
                            //asset type
                            entity = new PartialEntityVm { guid = entityInstanceProperties.Key.entityInstanceEntity.guid, name = entityInstanceProperties.Key.entityInstanceEntity.name },
                            entityInstanceGuid = entityInstanceProperties.Key.entityInstance == null ? null : entityInstanceProperties.Key.entityInstance.guid
                           
                        }
                    )

                });

            return results;
        }