コード例 #1
0
        public CollectionUpgradeManagerTests()
        {
            var factory = Substitute.For <ICosmosDbDistributedLockFactory>();
            var cosmosDbDistributedLock   = Substitute.For <ICosmosDbDistributedLock>();
            var collectionVersionWrappers = Substitute.For <IQueryable <CollectionVersion>, IDocumentQuery <CollectionVersion> >();

            factory.Create(Arg.Any <IDocumentClient>(), Arg.Any <Uri>(), Arg.Any <string>()).Returns(cosmosDbDistributedLock);
            cosmosDbDistributedLock.TryAcquireLock().Returns(true);

            _client = Substitute.For <IDocumentClient>();
            _client.CreateDocumentQuery <CollectionVersion>(Arg.Any <string>(), Arg.Any <SqlQuerySpec>(), Arg.Any <FeedOptions>())
            .Returns(collectionVersionWrappers);

            collectionVersionWrappers.AsDocumentQuery().ExecuteNextAsync <CollectionVersion>().Returns(new FeedResponse <CollectionVersion>(new List <CollectionVersion>()));

            var updaters = new ICollectionUpdater[] { new CollectionSettingsUpdater(NullLogger <CollectionSettingsUpdater> .Instance, _cosmosDataStoreConfiguration), };

            _manager = new CollectionUpgradeManager(updaters, _cosmosDataStoreConfiguration, factory, NullLogger <CollectionUpgradeManager> .Instance);
        }
コード例 #2
0
        public CollectionUpgradeManagerTests()
        {
            var factory = Substitute.For <ICosmosDbDistributedLockFactory>();
            var cosmosDbDistributedLock = Substitute.For <ICosmosDbDistributedLock>();
            var optionsMonitor          = Substitute.For <IOptionsMonitor <CosmosCollectionConfiguration> >();

            optionsMonitor.Get(Constants.CollectionConfigurationName).Returns(_cosmosCollectionConfiguration);

            factory.Create(Arg.Any <Container>(), Arg.Any <string>()).Returns(cosmosDbDistributedLock);
            cosmosDbDistributedLock.TryAcquireLock().Returns(true);

            _client = Substitute.For <Container>();

            var collectionVersionWrappers = Substitute.ForPartsOf <FeedIterator <CollectionVersion> >();

            _client.GetItemQueryIterator <CollectionVersion>(Arg.Any <QueryDefinition>(), Arg.Any <string>(), Arg.Any <QueryRequestOptions>())
            .Returns(collectionVersionWrappers);

            collectionVersionWrappers.ReadNextAsync(Arg.Any <CancellationToken>())
            .Returns(Substitute.ForPartsOf <FeedResponse <CollectionVersion> >());

            var updaters = new ICollectionUpdater[] { new FhirCollectionSettingsUpdater(_cosmosDataStoreConfiguration, optionsMonitor, NullLogger <FhirCollectionSettingsUpdater> .Instance), };

            _manager = new CollectionUpgradeManager(updaters, _cosmosDataStoreConfiguration, optionsMonitor, factory, NullLogger <CollectionUpgradeManager> .Instance);

            _containerResponse = Substitute.ForPartsOf <ContainerResponse>();

            var containerProperties = new ContainerProperties();

            containerProperties.IndexingPolicy = new IndexingPolicy
            {
                IncludedPaths = { },
                ExcludedPaths = { },
            };

            _containerResponse.Resource.Returns(containerProperties);
            _client.ReadContainerAsync(Arg.Any <ContainerRequestOptions>(), Arg.Any <CancellationToken>())
            .Returns(_containerResponse);
        }
コード例 #3
0
        public IntegrationTestCosmosDataStore()
        {
            _cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration
            {
                Host                  = Environment.GetEnvironmentVariable("CosmosDb:Host") ?? CosmosDbLocalEmulator.Host,
                Key                   = Environment.GetEnvironmentVariable("CosmosDb:Key") ?? CosmosDbLocalEmulator.Key,
                DatabaseId            = Environment.GetEnvironmentVariable("CosmosDb:DatabaseId") ?? "FhirTests",
                CollectionId          = Guid.NewGuid().ToString(),
                AllowDatabaseCreation = true,
                PreferredLocations    = Environment.GetEnvironmentVariable("CosmosDb:PreferredLocations")?.Split(';', StringSplitOptions.RemoveEmptyEntries),
            };

            var updaters = new ICollectionUpdater[]
            {
                new CollectionSettingsUpdater(NullLogger <CollectionSettingsUpdater> .Instance, _cosmosDataStoreConfiguration),
                new StoredProcedureInstaller(),
            };

            var dbLock = new CosmosDbDistributedLockFactory(Substitute.For <Func <IScoped <IDocumentClient> > >(), NullLogger <CosmosDbDistributedLock> .Instance);

            var upgradeManager = new CollectionUpgradeManager(updaters, _cosmosDataStoreConfiguration, dbLock, NullLogger <CollectionUpgradeManager> .Instance);
            IDocumentClientTestProvider testProvider = new DocumentClientReadWriteTestProvider();

            var documentClientInitializer = new DocumentClientInitializer(testProvider, NullLogger <DocumentClientInitializer> .Instance, upgradeManager, Substitute.For <IFhirRequestContextAccessor>());

            _documentClient = documentClientInitializer.CreateDocumentClient(_cosmosDataStoreConfiguration);
            documentClientInitializer.InitializeDataStore(_documentClient, _cosmosDataStoreConfiguration).GetAwaiter().GetResult();

            var cosmosDocumentQueryFactory = new CosmosDocumentQueryFactory(Substitute.For <IFhirRequestContextAccessor>(), NullFhirDocumentQueryLogger.Instance);

            _dataStore = new CosmosDataStore(
                new NonDisposingScope(_documentClient),
                _cosmosDataStoreConfiguration,
                cosmosDocumentQueryFactory,
                new RetryExceptionPolicyFactory(_cosmosDataStoreConfiguration),
                NullLogger <CosmosDataStore> .Instance);
        }
コード例 #4
0
        public async Task InitializeAsync()
        {
            var fhirStoredProcs = typeof(IStoredProcedure).Assembly
                                  .GetTypes()
                                  .Where(x => !x.IsAbstract && typeof(IStoredProcedure).IsAssignableFrom(x))
                                  .ToArray()
                                  .Select(type => (IStoredProcedure)Activator.CreateInstance(type));

            var optionsMonitor = Substitute.For <IOptionsMonitor <CosmosCollectionConfiguration> >();

            optionsMonitor.Get(CosmosDb.Constants.CollectionConfigurationName).Returns(_cosmosCollectionConfiguration);

            var searchParameterDefinitionManager = new SearchParameterDefinitionManager(ModelInfoProvider.Instance);

            searchParameterDefinitionManager.Start();

            _filebasedSearchParameterRegistry = new FilebasedSearchParameterRegistry(searchParameterDefinitionManager, ModelInfoProvider.Instance);

            var updaters = new ICollectionUpdater[]
            {
                new FhirCollectionSettingsUpdater(_cosmosDataStoreConfiguration, optionsMonitor, NullLogger <FhirCollectionSettingsUpdater> .Instance),
                new StoredProcedureInstaller(fhirStoredProcs),
                new CosmosDbStatusRegistryInitializer(
                    () => _filebasedSearchParameterRegistry,
                    new CosmosQueryFactory(
                        new CosmosResponseProcessor(Substitute.For <IFhirRequestContextAccessor>(), Substitute.For <IMediator>(), NullLogger <CosmosResponseProcessor> .Instance),
                        NullFhirCosmosQueryLogger.Instance)),
            };

            var dbLock = new CosmosDbDistributedLockFactory(Substitute.For <Func <IScoped <Container> > >(), NullLogger <CosmosDbDistributedLock> .Instance);

            var upgradeManager = new CollectionUpgradeManager(updaters, _cosmosDataStoreConfiguration, optionsMonitor, dbLock, NullLogger <CollectionUpgradeManager> .Instance);
            ICosmosClientTestProvider testProvider = new CosmosClientReadWriteTestProvider();

            var fhirRequestContextAccessor = new FhirRequestContextAccessor();
            var cosmosResponseProcessor    = Substitute.For <ICosmosResponseProcessor>();

            var responseProcessor         = new CosmosResponseProcessor(fhirRequestContextAccessor, Substitute.For <IMediator>(), NullLogger <CosmosResponseProcessor> .Instance);
            var handler                   = new FhirCosmosResponseHandler(() => new NonDisposingScope(_container), _cosmosDataStoreConfiguration, fhirRequestContextAccessor, responseProcessor);
            var documentClientInitializer = new FhirCosmosClientInitializer(testProvider, new[] { handler }, NullLogger <FhirCosmosClientInitializer> .Instance);

            _cosmosClient = documentClientInitializer.CreateCosmosClient(_cosmosDataStoreConfiguration);
            var fhirCollectionInitializer = new CollectionInitializer(_cosmosCollectionConfiguration.CollectionId, _cosmosDataStoreConfiguration, _cosmosCollectionConfiguration.InitialCollectionThroughput, upgradeManager, NullLogger <CollectionInitializer> .Instance);

            // Cosmos DB emulators throws errors when multiple collections are initialized concurrently.
            // Use the semaphore to only allow one initialization at a time.
            await CollectionInitializationSemaphore.WaitAsync();

            try
            {
                await documentClientInitializer.InitializeDataStore(_cosmosClient, _cosmosDataStoreConfiguration, new List <ICollectionInitializer> {
                    fhirCollectionInitializer
                });

                _container = documentClientInitializer.CreateFhirContainer(_cosmosClient, _cosmosDataStoreConfiguration.DatabaseId, _cosmosCollectionConfiguration.CollectionId);
            }
            finally
            {
                CollectionInitializationSemaphore.Release();
            }

            var cosmosDocumentQueryFactory = new CosmosQueryFactory(cosmosResponseProcessor, NullFhirCosmosQueryLogger.Instance);

            var documentClient = new NonDisposingScope(_container);

            _fhirDataStore = new CosmosFhirDataStore(
                documentClient,
                _cosmosDataStoreConfiguration,
                optionsMonitor,
                cosmosDocumentQueryFactory,
                new RetryExceptionPolicyFactory(_cosmosDataStoreConfiguration),
                NullLogger <CosmosFhirDataStore> .Instance,
                new VersionSpecificModelInfoProvider(),
                Options.Create(new CoreFeatureConfiguration()));

            _fhirOperationDataStore = new CosmosFhirOperationDataStore(
                documentClient,
                _cosmosDataStoreConfiguration,
                optionsMonitor,
                new RetryExceptionPolicyFactory(_cosmosDataStoreConfiguration),
                new CosmosQueryFactory(responseProcessor, new NullFhirCosmosQueryLogger()),
                NullLogger <CosmosFhirOperationDataStore> .Instance);

            _fhirStorageTestHelper = new CosmosDbFhirStorageTestHelper(
                _container,
                _cosmosDataStoreConfiguration.DatabaseId,
                _cosmosCollectionConfiguration.CollectionId);
        }
コード例 #5
0
        public async Task InitializeAsync()
        {
            var fhirStoredProcs = typeof(IStoredProcedure).Assembly
                                  .GetTypes()
                                  .Where(x => !x.IsAbstract && typeof(IStoredProcedure).IsAssignableFrom(x))
                                  .ToArray()
                                  .Select(type => (IStoredProcedure)Activator.CreateInstance(type));

            var optionsMonitor = Substitute.For <IOptionsMonitor <CosmosCollectionConfiguration> >();

            optionsMonitor.Get(CosmosDb.Constants.CollectionConfigurationName).Returns(_cosmosCollectionConfiguration);

            _fhirRequestContextAccessor.RequestContext.CorrelationId.Returns(Guid.NewGuid().ToString());
            _fhirRequestContextAccessor.RequestContext.RouteName.Returns("routeName");

            _searchParameterDefinitionManager = new SearchParameterDefinitionManager(ModelInfoProvider.Instance, _mediator, () => _searchService.CreateMockScope(), NullLogger <SearchParameterDefinitionManager> .Instance);
            await _searchParameterDefinitionManager.StartAsync(CancellationToken.None);

            _supportedSearchParameterDefinitionManager = new SupportedSearchParameterDefinitionManager(_searchParameterDefinitionManager);
            var searchableSearchParameterDefinitionManager = new SearchableSearchParameterDefinitionManager(_searchParameterDefinitionManager, _fhirRequestContextAccessor);

            _filebasedSearchParameterStatusDataStore = new FilebasedSearchParameterStatusDataStore(_searchParameterDefinitionManager, ModelInfoProvider.Instance);

            IMediator mediator = Substitute.For <IMediator>();

            var updaters = new ICollectionUpdater[]
            {
                new FhirCollectionSettingsUpdater(_cosmosDataStoreConfiguration, optionsMonitor, NullLogger <FhirCollectionSettingsUpdater> .Instance),
                new StoredProcedureInstaller(fhirStoredProcs),
                new CosmosDbSearchParameterStatusInitializer(
                    () => _filebasedSearchParameterStatusDataStore,
                    new CosmosQueryFactory(
                        new CosmosResponseProcessor(_fhirRequestContextAccessor, mediator, Substitute.For <ICosmosQueryLogger>(), NullLogger <CosmosResponseProcessor> .Instance),
                        NullFhirCosmosQueryLogger.Instance),
                    _cosmosDataStoreConfiguration),
            };

            var dbLock = new CosmosDbDistributedLockFactory(Substitute.For <Func <IScoped <Container> > >(), NullLogger <CosmosDbDistributedLock> .Instance);

            var upgradeManager = new CollectionUpgradeManager(updaters, _cosmosDataStoreConfiguration, optionsMonitor, dbLock, NullLogger <CollectionUpgradeManager> .Instance);
            ICosmosClientTestProvider testProvider = new CosmosClientReadWriteTestProvider();

            var cosmosResponseProcessor = Substitute.For <ICosmosResponseProcessor>();

            var responseProcessor           = new CosmosResponseProcessor(_fhirRequestContextAccessor, mediator, Substitute.For <ICosmosQueryLogger>(), NullLogger <CosmosResponseProcessor> .Instance);
            var handler                     = new FhirCosmosResponseHandler(() => new NonDisposingScope(_container), _cosmosDataStoreConfiguration, _fhirRequestContextAccessor, responseProcessor);
            var retryExceptionPolicyFactory = new RetryExceptionPolicyFactory(_cosmosDataStoreConfiguration, _fhirRequestContextAccessor);
            var documentClientInitializer   = new FhirCosmosClientInitializer(testProvider, () => new[] { handler }, retryExceptionPolicyFactory, NullLogger <FhirCosmosClientInitializer> .Instance);

            _cosmosClient = documentClientInitializer.CreateCosmosClient(_cosmosDataStoreConfiguration);
            var fhirCollectionInitializer = new CollectionInitializer(_cosmosCollectionConfiguration, _cosmosDataStoreConfiguration, upgradeManager, retryExceptionPolicyFactory, testProvider, NullLogger <CollectionInitializer> .Instance);

            // Cosmos DB emulators throws errors when multiple collections are initialized concurrently.
            // Use the semaphore to only allow one initialization at a time.
            await CollectionInitializationSemaphore.WaitAsync();

            try
            {
                await documentClientInitializer.InitializeDataStore(_cosmosClient, _cosmosDataStoreConfiguration, new List <ICollectionInitializer> {
                    fhirCollectionInitializer
                });

                _container = documentClientInitializer.CreateFhirContainer(_cosmosClient, _cosmosDataStoreConfiguration.DatabaseId, _cosmosCollectionConfiguration.CollectionId);
            }
            finally
            {
                CollectionInitializationSemaphore.Release();
            }

            var cosmosDocumentQueryFactory = new CosmosQueryFactory(cosmosResponseProcessor, NullFhirCosmosQueryLogger.Instance);

            var documentClient = new NonDisposingScope(_container);

            _searchParameterStatusDataStore = new CosmosDbSearchParameterStatusDataStore(
                () => documentClient,
                _cosmosDataStoreConfiguration,
                cosmosDocumentQueryFactory);

            IOptions <CoreFeatureConfiguration> options = Options.Create(new CoreFeatureConfiguration());

            _fhirDataStore = new CosmosFhirDataStore(
                documentClient,
                _cosmosDataStoreConfiguration,
                optionsMonitor,
                cosmosDocumentQueryFactory,
                retryExceptionPolicyFactory,
                NullLogger <CosmosFhirDataStore> .Instance,
                options,
                new Lazy <ISupportedSearchParameterDefinitionManager>(_supportedSearchParameterDefinitionManager),
                ModelInfoProvider.Instance);

            _fhirOperationDataStore = new CosmosFhirOperationDataStore(
                documentClient,
                _cosmosDataStoreConfiguration,
                optionsMonitor,
                retryExceptionPolicyFactory,
                new CosmosQueryFactory(responseProcessor, new NullFhirCosmosQueryLogger()),
                NullLogger <CosmosFhirOperationDataStore> .Instance);

            var searchParameterExpressionParser = new SearchParameterExpressionParser(new ReferenceSearchValueParser(_fhirRequestContextAccessor));
            var expressionParser     = new ExpressionParser(() => searchableSearchParameterDefinitionManager, searchParameterExpressionParser);
            var searchOptionsFactory = new SearchOptionsFactory(expressionParser, () => searchableSearchParameterDefinitionManager, options, _fhirRequestContextAccessor, Substitute.For <ISortingValidator>(), NullLogger <SearchOptionsFactory> .Instance);

            ICosmosDbCollectionPhysicalPartitionInfo cosmosDbPhysicalPartitionInfo = Substitute.For <ICosmosDbCollectionPhysicalPartitionInfo>();

            cosmosDbPhysicalPartitionInfo.PhysicalPartitionCount.Returns(1);

            _searchService = new FhirCosmosSearchService(
                searchOptionsFactory,
                _fhirDataStore,
                new QueryBuilder(),
                _fhirRequestContextAccessor,
                _cosmosDataStoreConfiguration,
                cosmosDbPhysicalPartitionInfo,
                new QueryPartitionStatisticsCache(),
                Enumerable.Empty <ICosmosExpressionRewriter>(),
                NullLogger <FhirCosmosSearchService> .Instance);

            await _searchParameterDefinitionManager.EnsureInitializedAsync(CancellationToken.None);

            ISearchParameterSupportResolver searchParameterSupportResolver = Substitute.For <ISearchParameterSupportResolver>();

            searchParameterSupportResolver.IsSearchParameterSupported(Arg.Any <SearchParameterInfo>()).Returns((true, false));

            _searchParameterStatusManager = new SearchParameterStatusManager(
                _searchParameterStatusDataStore,
                _searchParameterDefinitionManager,
                searchParameterSupportResolver,
                mediator,
                NullLogger <SearchParameterStatusManager> .Instance);

            _fhirStorageTestHelper = new CosmosDbFhirStorageTestHelper(_container);
        }
コード例 #6
0
        public async void Test()
        {
            _databaseConnection.Connect();

            /////////////////////////////////////
            // OPERATIONAL, CONTEXUAL SCOPE... //
            /////////////////////////////////////

            // create a Writer to write to the database
            IWriter writer = new Writer(_databaseConnection);
            // create a Reader to read from the database
            IReader reader = new Reader(_databaseConnection);
            // create an Updater to update the database
            IUpdater updater = new Updater(_databaseConnection);

            Entry exampleMongoDBEntry = new Entry();

            exampleMongoDBEntry.Message = "Hello";

            // write the object to the "MyFirstCollection" Collection that exists within the
            // previously referenced "MyFirstDatabase" that was used to create the "writer" object
            writer.Write <Entry>("MyFirstCollection", exampleMongoDBEntry);

            IEnumerable <Entry> readEntrys = reader.Read <Entry>("MyFirstCollection", // within this collection...
                                                                 "Message",           // for the object field "Description"
                                                                 "Hello");            // return matches for 'Hello'

            Assert.AreEqual(1, readEntrys.Count());

            ////////////////////////////////////
            // AND ASYNCHRONOUS OPERATIONS... //
            ////////////////////////////////////

            // read, write and update asynchronously using System.Threading.Task
            IAsyncReader asyncReader = new AsyncReader(reader);

            readEntrys = await asyncReader.ReadAsync <Entry>("MyFirstCollection", "Message", "Hello");

            Assert.AreEqual(1, readEntrys.Count());

            IAsyncWriter  asyncWriter  = new AsyncWriter(writer);
            IAsyncUpdater asyncUpdater = new AsyncUpdater(updater);

            // or delegate call backs
            IAsyncDelegateReader asyncDelegateReader = new AsyncDelegateReader(reader);

            asyncDelegateReader.AsyncReadCompleted += new ReadCompletedEvent(readerCallBack);
            asyncDelegateReader.ReadAsync <Entry>("MyFirstCollection", "Message", "Hello");
            _readerAutoResetEvent.WaitOne();

            Assert.AreEqual(1, _asyncReadResults.Count());

            IAsyncDelegateWriter  asyncDelegateWriter  = new AsyncDelegateWriter(writer);
            IAsyncDelegateUpdater asyncDelegateUpdater = new AsyncDelegateUpdater(updater);

            /////////////////////////////////////////////
            // FOR A SERVER, DATABASE OR COLLECTION... //
            /////////////////////////////////////////////

            // get a little higher level with the EasyMongo.Database namespace to target a database for operations
            IDatabaseReader  databaseReader  = new DatabaseReader(reader, asyncReader);
            IDatabaseWriter  databaseWriter  = new DatabaseWriter(writer, asyncWriter);
            IDatabaseUpdater databaseUpdater = new DatabaseUpdater(updater, asyncUpdater);

            // or a little lower level with the EasyMongo.Collection namespace to target a specific Collection
            ICollectionReader  collectionReader  = new CollectionReader(databaseReader, "MyFirstCollection");
            ICollectionWriter  collectionWriter  = new CollectionWriter(databaseWriter, "MyFirstCollection");
            ICollectionUpdater collectionUpdater = new CollectionUpdater(databaseUpdater, "MyFirstCollection");

            ///////////////////////////////////////////////
            // TO RESTRICT CLIENT SCOPE (LAW OF DEMETER) //
            ///////////////////////////////////////////////

            // operate only against "MyFirstDatabase"'s "MySecondCollection"
            readEntrys = collectionReader.Read <Entry>("Message", "Hello");
            Assert.AreEqual(1, readEntrys.Count());

            /////////////////////
            // GENERIC CLASSES //
            /////////////////////

            // Instead of defining generic type arguments at the method level,
            // you can do it once at the class declaration
            IWriter <Entry> writerT = new Writer <Entry>(writer);

            writerT.Write("MySecondCollection", new Entry()
            {
                Message = "Goodbye World (Generically)"
            });

            ///////////////////////////////
            // SIMPLIFY CREATION VIA IoC //
            ///////////////////////////////

            // because EasyMongo is a componentized framework built with blocks of functionality, EasyMongo
            // works great with DI containers and Inversion of Control.
            // here's an example of using the nuget Ninject extension to load EasyMongo mappings and a conn
            // string from configuration
            Ninject.IKernel            kernel             = new Ninject.StandardKernel();
            ICollectionUpdater <Entry> collectionUpdaterT = kernel.TryGet <ICollectionUpdater <Entry> >();

            // the alternative to this would be:
            IServerConnection   serverConn     = new ServerConnection(LOCAL_MONGO_SERVER_CONNECTION_STRING);
            IDatabaseConnection databaseConnn  = new DatabaseConnection(serverConn, "MyFirstDatabase");
            IDatabaseUpdater    databaseUpdatr = new DatabaseUpdater(updater, asyncUpdater);
            ICollectionUpdater  collectionUpdaterTheHardWay = new CollectionUpdater(databaseUpdater, "MySecondCollection");

            /////////////////////////
            // SIMPLE QUERIES...   //
            /////////////////////////

            databaseReader.Read <Entry>("MyFirstCollection", "Message", "Hello");
            readEntrys = await databaseReader.ReadAsync <Entry>("MyFirstCollection", "Message", "Hello");

            Assert.AreEqual(1, readEntrys.Count());

            /////////////////////////
            // POWERFUL QUERIES... //
            /////////////////////////

            // when more robust querying is needed leverage power of underlying MongoDB driver IMongoQuery
            IMongoQuery query1 = Query.Matches("Message", new BsonRegularExpression("HE", "i"));

            IEnumerable <Entry> queryResults = reader.Execute <Entry>("MyFirstCollection", query1);

            Assert.AreEqual(1, queryResults.Count());
            Assert.AreEqual("Hello", queryResults.ElementAt(0).Message);

            //////////////////////
            // AND COMBINATIONS //
            //////////////////////

            Entry exampleMongoDBEntry2 = new Entry();

            exampleMongoDBEntry2.Message = "Hello Again";

            Entry exampleMongoDBEntry3 = new Entry();

            exampleMongoDBEntry3.Message = "Goodbye";

            writer.Write <Entry>("MyFirstCollection", exampleMongoDBEntry2);
            writer.Write <Entry>("MyFirstCollection", exampleMongoDBEntry3);

            // "AND" multiple IMongoQueries...
            IMongoQuery query2 = Query.Matches("Message", new BsonRegularExpression("Again"));

            queryResults = reader.ExecuteAnds <Entry>("MyFirstCollection", new [] { query1, query2 });
            Assert.AreEqual(1, queryResults.Count());
            Assert.AreEqual("Hello Again", queryResults.ElementAt(0).Message);

            // "OR" multiple IMongoQueries...
            IMongoQuery query3 = Query.Matches("Message", new BsonRegularExpression("Goo"));

            queryResults = reader.ExecuteOrs <Entry>("MyFirstCollection", new[] { query1, query2, query3 });
            Assert.AreEqual(3, queryResults.Count());
            Assert.AreEqual("Hello", queryResults.ElementAt(0).Message);
            Assert.AreEqual("Hello Again", queryResults.ElementAt(1).Message);
            Assert.AreEqual("Goodbye", queryResults.ElementAt(2).Message);
        }