public override IReadOnlyCollection <Row> Initialize()
 {
     Db.Config.DatabaseConnectionString.WithReader(Query, reader =>
     {
         Schema = new RowSchema(reader, PrimaryKeyColumns);
         _data  = new ReducableDictionary <object[], Row>(Schema.RowKeyEqualityComparer);
         while (reader.Read())
         {
             var row = Schema.ReadRow(reader);
             _data.Add(row.Key, row);
         }
     });
     return(_data.Values.ToArray());
 }
        /// <summary>
        /// Create a new instance of <see cref="SqlCachedQuery"/>
        /// </summary>
        /// <param name="db">Database this query belongs to</param>
        /// <param name="query">UserQuery that is encapsulated by this query</param>
        /// <param name="keyExtractor">Function to extract <typeparamref name="TKey"/> from <typeparamref name="TRow"/></param>
        /// <param name="keyComparerFactory">Comparer to compare <typeparamref name="TKey"/></param>
        /// <param name="cachingType">Type of cache used to detect changes</param>
        /// <param name="primaryKeyColumn">The column used as primary key</param>
        /// <param name="additionalPrimaryKeyColumns">Additional column names for the primary key</param>
        /// <param name="rowFactory">Function to transform <see cref="Row"/> into <typeparamref name="TRow"/></param>
        internal MappedSqlCachedQuery(Database db, string query, Func <Row, TRow> rowFactory, Func <TRow, TKey> keyExtractor, Func <RowSchema, IEqualityComparer <TKey> > keyComparerFactory, CachingType cachingType, string primaryKeyColumn, params string[] additionalPrimaryKeyColumns) : base(Guid.NewGuid())
        {
            _rowFactory   = rowFactory;
            _keyExtractor = keyExtractor;

            switch (cachingType)
            {
            case CachingType.InMemory:
                _view = new InMemoryCache(db, query, new[] { primaryKeyColumn }.Union(additionalPrimaryKeyColumns).ToArray());
                break;

            case CachingType.SqlTable:
                _view = new SqlTableCache(db, query, new[] { primaryKeyColumn }.Union(additionalPrimaryKeyColumns).ToArray());
                break;

            case CachingType.SqlInMemoryTable:
                _view = new SqlMemoryTableCache(db, query, new[] { primaryKeyColumn }.Union(additionalPrimaryKeyColumns).ToArray());
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(cachingType), cachingType, null);
            }


            lock (_dataAccessLock)
            {
                _view.Invalidated += ViewOnInvalidated;
                _disposeHelper.Attach(() => _view.Invalidated -= ViewOnInvalidated);
                var data = _view.Initialize();

                _rows = new ReducableDictionary <TKey, TRow>(data.Count, keyComparerFactory(_view.Schema));
                foreach (var row in data)
                {
                    var entry = rowFactory(row);
                    var key   = keyExtractor(entry);
                    _rows.Add(key, entry);
                }

                _disposeHelper.Attach(_view);
            }
        }