Exemplo n.º 1
0
        private IEnumerable <TRootEntity> Fetch(int page, int size, TotalCount totalCount, Map <TRootEntity> map)
        {
            totalCount.Value = 0;

            using (var reader = _databaseAccessor.CreateFetchReader(_queryOptions, out Action dispose))
            {
                TRootEntity rootEntity  = null;
                Row         prevRow     = null;
                int         currentPage = 0;
                int         currentSize = 0;

                Dictionary <MapRuleBasic, Dictionary <string, bool> > mapUniqueKeyValueCache = new Dictionary <MapRuleBasic, Dictionary <string, bool> >();

                while (reader.Read())
                {
                    MapRuleBasic rootMapRuleBasic = map.RootMapRuleBasic;

                    Row currentRow = Row.CreateReadRow(reader, rootMapRuleBasic);

                    List <string> uniqueKeys = new List <string>();

                    if (currentRow.CanCreate(prevRow, uniqueKeys))
                    {
                        totalCount.Value++;

                        if (rootEntity != null)
                        {
                            SetReNestNodes(map, rootEntity);
                            yield return(rootEntity);
                        }

                        rootEntity = null;

                        if (currentPage == 0 || currentSize % size == 0)
                        {
                            currentPage++;
                            currentSize = 0;
                        }

                        currentSize++;

                        if (currentPage == page)
                        {
                            rootEntity = rootMapRuleBasic.GetEntity(currentRow, rootEntity) as TRootEntity;
                        }
                    }

                    if (rootEntity == null)
                    {
                        prevRow = currentRow;
                        continue;
                    }

                    if (_queryOptions.IsFlatFormat)
                    {
                        continue;
                    }

                    uniqueKeys.AddRange(currentRow.UniqueKeys);

                    foreach (var mapRuleBasic in map.MapRuleBasicListWithoutRoot)
                    {
                        currentRow.SetMapRuleBasic(mapRuleBasic);

                        // ユニークキーの値がNULL、または、依然と重複している場合は、処理をしない >>

                        StringBuilder uniqueKeyValuesBuilder = new StringBuilder();

                        bool canContinue = true;

                        foreach (var key in currentRow.UniqueKeys)
                        {
                            if (currentRow[key] == DBNull.Value)
                            {
                                canContinue = false;
                            }

                            uniqueKeyValuesBuilder.Append(currentRow[key].ToString() + ":");
                        }

                        string uniqueKeyValues = uniqueKeyValuesBuilder.ToString();

                        if (mapUniqueKeyValueCache.TryGetValue(mapRuleBasic, out Dictionary <string, bool> values))
                        {
                            if (values.ContainsKey(uniqueKeyValues))
                            {
                                canContinue = false;
                            }
                            ;
                        }
                        else
                        {
                            mapUniqueKeyValueCache[mapRuleBasic] = new Dictionary <string, bool>();
                        }

                        mapUniqueKeyValueCache[mapRuleBasic][uniqueKeyValues] = true;

                        if (!canContinue)
                        {
                            continue;
                        }

                        // ユニークキーが重複している場合は、処理をしない <<

                        object       parentEntity = rootEntity;
                        PropertyInfo property     = null;

                        foreach (var section in mapRuleBasic.ExpressionSections)
                        {
                            if (property != null && !property.PropertyType.IsList())
                            {
                                parentEntity = property.Get(parentEntity);
                            }
                            if (property != null && property.PropertyType.IsList())
                            {
                                var list = property.Get(parentEntity) as IEnumerable;
                                foreach (var item in list)
                                {
                                    parentEntity = item;
                                }
                            }

                            Dictionary <string, PropertyInfo> propertyMap = parentEntity.GetType().GetPropertyMap(BindingFlags.GetProperty | BindingFlags.SetProperty, PropertyTypeFilters.OnlyClass);

                            property = propertyMap[section];
                        }

                        if (mapRuleBasic.IsToMany)
                        {
                            object list = property.Get(parentEntity);

                            if (list == null)
                            {
                                if (property.PropertyType.IsArray)
                                {
                                    list = Array.CreateInstance(mapRuleBasic.EntityType, 0);
                                }
                                else if (property.PropertyType == typeof(IEnumerable <>).MakeGenericType(mapRuleBasic.EntityType))
                                {
                                    list = typeof(List <>).MakeGenericType(mapRuleBasic.EntityType).Create();
                                }
                                else
                                {
                                    list = property.PropertyType.Create();
                                }

                                property.Set(parentEntity, list);
                            }

                            object entity = mapRuleBasic.GetEntity(currentRow, rootEntity);

                            if (property.PropertyType.IsArray)
                            {
                                Array array    = (Array)list;
                                Array newArray = Array.CreateInstance(mapRuleBasic.EntityType, array.Length + 1);

                                array.CopyTo(newArray, 0);
                                newArray.SetValue(entity, array.Length);

                                property.Set(parentEntity, newArray);
                            }
                            else if (property.PropertyType == typeof(IEnumerable <>).MakeGenericType(mapRuleBasic.EntityType))
                            {
                                dynamic dynamicList = typeof(List <>).MakeGenericType(mapRuleBasic.EntityType).Create();
                                dynamicList.AddRange(list as dynamic);
                                dynamicList.Add(entity as dynamic);

                                property.Set(parentEntity, dynamicList as object);
                            }
                            else
                            {
                                MethodInfo method = list.GetType().GetMethod("Add", new Type[] { mapRuleBasic.EntityType });
                                method.Invoke(list, new object[] { entity });
                            }
                        }
                        else
                        {
                            object entity = mapRuleBasic.GetEntity(currentRow, rootEntity);
                            property.Set(parentEntity, entity);
                        }
                    }

                    prevRow = currentRow;
                }

                if (rootEntity != null)
                {
                    SetReNestNodes(map, rootEntity);
                    yield return(rootEntity);
                }

                reader.Close();
                dispose();
            }
        }