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(); } }