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