public static void DoNotBeConfusedByRepeatedFieldNames()
        {
            var databaseInitialisation = @"
				CREATE TABLE test(id INTEGER, name TEXT);
				INSERT INTO test VALUES (1, 'Bob');
				INSERT INTO test VALUES (2, 'Jack');
			"            ;

            int?fieldCount = null;

            using (var reusableConnection = CreateReusableConnection(databaseInitialisation))
            {
                var proxy = new SqlProxy(() => reusableConnection, queryRecorder: criteria => { }, scalarQueryRecorder: criteria => { }, nonQueryRowCountRecorder: criteria => { });
                using (var proxyConnection = new RemoteSqlConnectionClient(proxy, proxy.GetNewConnectionId()))
                {
                    using (var command = proxyConnection.CreateCommand("SELECT id, id, name FROM Test"))
                    {
                        proxyConnection.Open();
                        using (var reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                fieldCount = reader.FieldCount;
                                break;
                            }
                        }
                    }
                }
            }

            Assert.NotNull(fieldCount);
            Assert.Equal(3, fieldCount.Value);
        }
        public static void ProxyAndReplayQueryForInMemorySqliteDatabase()
        {
            var databaseInitialisation = @"
				CREATE TABLE test(id INTEGER, name TEXT);
				INSERT INTO test VALUES (1, 'Bob');
				INSERT INTO test VALUES (2, 'Jack');
			"            ;

            // Create an in-memory database and perform a query that will populate a cache that will allow replaying those queries without having to
            // hit the database. The read-write "DictionaryCache" requires a way to execute SQL (so that it can take a SQL statement and generate a
            // disconnected DataSet to cache the contents of) but we'll only need the read methods of the cache class - so, before throwing away
            // the DictionaryCache reference after loading the data from the db, get a read-only wrapper so that the SQL Runner that the read-write
            // cache requires can be tidied up.
            var namesFromSqlCalls = new List <string>();
            ReadOnlyDictionaryCache readOnlyCache;

            using (var reusableConnection = CreateReusableConnection(databaseInitialisation))
            {
                var cache = new DictionaryCache(new SqliteRunner(reusableConnection), infoLogger: Console.WriteLine);
                var proxy = new SqlProxy(() => reusableConnection, cache.QueryRecorder, cache.ScalarQueryRecorder, cache.NonQueryRowCountRecorder);
                using (var proxyConnection = new RemoteSqlConnectionClient(proxy, proxy.GetNewConnectionId()))
                {
                    using (var command = proxyConnection.CreateCommand("SELECT * FROM test"))
                    {
                        proxyConnection.Open();
                        using (var reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                namesFromSqlCalls.Add(reader.GetString(reader.GetOrdinal("Name")));
                            }
                        }
                    }
                }
                readOnlyCache = new ReadOnlyDictionaryCache(cache);
            }

            // Use the read-only cache to create an alternate IDbConnection instance (a SqlReplayer) that will allow the same SQL statement to be
            // executed and the same data returned, without actually requiring the database
            var namesFromReplayedCalls = new List <string>();
            var replayer = new SqlReplayer(readOnlyCache.DataRetriever, readOnlyCache.ScalarDataRetriever, readOnlyCache.NonQueryRowCountRetriever);

            using (var replayerConnection = new RemoteSqlConnectionClient(replayer, replayer.GetNewConnectionId()))
            {
                replayerConnection.ConnectionString = _sqliteInMemoryCacheConnectionString;
                using (var command = replayerConnection.CreateCommand("SELECT * FROM test"))
                {
                    replayerConnection.Open();
                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            namesFromReplayedCalls.Add(reader.GetString(reader.GetOrdinal("Name")));
                        }
                    }
                }
            }

            var expectedValues = new List <string> {
                "Bob", "Jack"
            };

            Assert.Equal(expectedValues, namesFromSqlCalls);
            Assert.Equal(expectedValues, namesFromReplayedCalls);
        }