private void LoadList(SoodaTransaction transaction, SoodaWhereClause whereClause, SoodaOrderBy orderBy, int startIdx, int pageCount, SoodaSnapshotOptions options, string[] involvedClassNames, bool useCache)
        {
            ISoodaObjectFactory factory = transaction.GetFactory(classInfo);
            string cacheKey             = null;

            if (useCache)
            {
                // cache makes sense only on clean database
                if (!transaction.HasBeenPrecommitted(classInfo))
                {
                    cacheKey = SoodaCache.GetCollectionKey(classInfo, whereClause);
                }

                IEnumerable keysCollection = transaction.LoadCollectionFromCache(cacheKey, logger);
                if (keysCollection != null)
                {
                    foreach (object o in keysCollection)
                    {
                        SoodaObject obj = factory.GetRef(transaction, o);
                        // this binds to cache
                        obj.EnsureFieldsInited();
                        items.Add(obj);
                    }

                    if (orderBy != null)
                    {
                        items.Sort(orderBy.GetComparer());
                    }
                    count = items.Count;

                    if (startIdx > 0)
                    {
                        if (startIdx < count)
                        {
                            items.RemoveRange(0, startIdx);
                        }
                        else
                        {
                            items.Clear();
                        }
                    }

                    if (pageCount != -1 && pageCount < items.Count)
                    {
                        items.RemoveRange(pageCount, items.Count - pageCount);
                    }

                    return;
                }
            }

            SoodaDataSource ds = transaction.OpenDataSource(classInfo.GetDataSource());

            if ((options & SoodaSnapshotOptions.KeysOnly) != 0)
            {
                if (pageCount != -1)
                {
                    using (IDataReader reader = ds.LoadMatchingPrimaryKeys(transaction.Schema, classInfo, whereClause, orderBy, 0, -1))
                    {
                        count = 0;
                        while (reader.Read())
                        {
                            count++;
                        }
                    }
                }
                using (IDataReader reader = ds.LoadMatchingPrimaryKeys(transaction.Schema, classInfo, whereClause, orderBy, startIdx, pageCount))
                {
                    while (reader.Read())
                    {
                        SoodaObject obj = SoodaObject.GetRefFromKeyRecordHelper(transaction, factory, reader);
                        items.Add(obj);
                    }
                    if (pageCount == -1)
                    {
                        count = items.Count;
                    }
                }
            }
            else
            {
                if (pageCount != -1)
                {
                    using (IDataReader reader = ds.LoadMatchingPrimaryKeys(transaction.Schema, classInfo, whereClause, orderBy, 0, -1))
                    {
                        count = 0;
                        while (reader.Read())
                        {
                            count++;
                        }
                    }
                }

                TableInfo[] loadedTables;

                using (IDataReader reader = ds.LoadObjectList(transaction.Schema, classInfo, whereClause, orderBy, startIdx, pageCount, options, out loadedTables))
                {
                    while (reader.Read())
                    {
                        SoodaObject obj = SoodaObject.GetRefFromRecordHelper(transaction, factory, reader, 0, loadedTables, 0);
                        if ((options & SoodaSnapshotOptions.VerifyAfterLoad) != 0 && whereClause != null && !whereClause.Matches(obj, false))
                        {
                            continue; // don't add the object
                        }
                        items.Add(obj);
                    }
                    if (pageCount == -1)
                    {
                        count = items.Count;
                    }
                }
            }

            if (cacheKey != null && useCache && startIdx == 0 && pageCount == -1 && involvedClassNames != null)
            {
                TimeSpan expirationTimeout;
                bool     slidingExpiration;

                if (transaction.CachingPolicy.GetExpirationTimeout(
                        classInfo, whereClause, orderBy, startIdx, pageCount, items.Count,
                        out expirationTimeout, out slidingExpiration))
                {
                    transaction.StoreCollectionInCache(cacheKey, classInfo, items, involvedClassNames, (options & SoodaSnapshotOptions.KeysOnly) == 0, expirationTimeout, slidingExpiration);
                }
            }
        }
        protected override void LoadData()
        {
            SoodaDataSource ds = transaction.OpenDataSource(classInfo.GetDataSource());

            TableInfo[] loadedTables;

            items      = new Dictionary <SoodaObject, int>();
            itemsArray = new List <SoodaObject>();

            ISoodaObjectFactory factory     = transaction.GetFactory(classInfo);
            SoodaWhereClause    whereClause = new SoodaWhereClause(Soql.FieldEqualsParam(childRefField, 0), parentObject.GetPrimaryKeyValue());

            if (additionalWhereClause != null)
            {
                whereClause = whereClause.Append(additionalWhereClause);
            }

            string cacheKey = null;

            if (cached)
            {
                // cache makes sense only on clean database
                if (!transaction.HasBeenPrecommitted(classInfo.GetRootClass()))
                {
                    cacheKey = SoodaCache.GetCollectionKey(classInfo, whereClause);
                }
            }
            IEnumerable keysCollection = transaction.LoadCollectionFromCache(cacheKey, logger);

            if (keysCollection != null)
            {
                foreach (object o in keysCollection)
                {
                    SoodaObject obj = factory.GetRef(transaction, o);
                    // this binds to cache
                    obj.EnsureFieldsInited();

                    if (tempItems != null)
                    {
                        CollectionChange change;
                        if (tempItems.TryGetValue(obj, out change) && change == CollectionChange.Removed)
                        {
                            continue;
                        }
                    }

                    items.Add(obj, itemsArray.Count);
                    itemsArray.Add(obj);
                }
            }
            else
            {
                using (IDataReader reader = ds.LoadObjectList(transaction.Schema, classInfo, whereClause, null, 0, -1, SoodaSnapshotOptions.Default, out loadedTables))
                {
                    List <SoodaObject> readObjects = null;

                    if (cached)
                    {
                        readObjects = new List <SoodaObject>();
                    }

                    while (reader.Read())
                    {
                        SoodaObject obj = SoodaObject.GetRefFromRecordHelper(transaction, factory, reader, 0, loadedTables, 0);
                        if (readObjects != null)
                        {
                            readObjects.Add(obj);
                        }

                        if (tempItems != null)
                        {
                            CollectionChange change;
                            if (tempItems.TryGetValue(obj, out change) && change == CollectionChange.Removed)
                            {
                                continue;
                            }
                        }

                        items.Add(obj, itemsArray.Count);
                        itemsArray.Add(obj);
                    }
                    if (cached)
                    {
                        TimeSpan expirationTimeout;
                        bool     slidingExpiration;

                        if (transaction.CachingPolicy.GetExpirationTimeout(
                                classInfo, whereClause, null, 0, -1, readObjects.Count,
                                out expirationTimeout, out slidingExpiration))
                        {
                            transaction.StoreCollectionInCache(cacheKey, classInfo, readObjects, null, true, expirationTimeout, slidingExpiration);
                        }
                    }
                }
            }

            if (tempItems != null)
            {
                foreach (KeyValuePair <SoodaObject, CollectionChange> entry in tempItems)
                {
                    if (entry.Value == CollectionChange.Added)
                    {
                        SoodaObject obj = (SoodaObject)entry.Key;

                        if (!items.ContainsKey(obj))
                        {
                            items.Add(obj, itemsArray.Count);
                            itemsArray.Add(obj);
                        }
                    }
                }
            }
        }