public async Task TestCosmosDbAzureCosmosDbOk()
        {
            //SETUP
            var config = new ConfigurationBuilder()
                         .AddUserSecrets <Startup>()
                         .Build();
            var builder = new DbContextOptionsBuilder <NoSqlDbContext>()
                          .UseCosmos(
                config["CosmosUrl"],
                config["CosmosKey"],
                GetType().Name);

            using (var context = new NoSqlDbContext(builder.Options))
            {
                await context.Database.EnsureCreatedAsync();

                //ATTEMPT
                var book = NoSqlTestData.CreateDummyNoSqlBook();
                context.Add(book);
                await context.SaveChangesAsync();

                //VERIFY
                context.Books.Find(book.BookId).ShouldNotBeNull();
            }
        }
        public async Task TestCosmosDbAzureCosmosDbOk()
        {
            //SETUP
            var config = new ConfigurationBuilder()
                         .AddUserSecrets <Startup>()
                         .Build();
            var builder = new DbContextOptionsBuilder <NoSqlDbContext>()
                          .UseCosmos(
                config["CosmosUrl"],
                config["CosmosKey"],
                nameof(TestNoSqlDbContext));

            using (var context = new NoSqlDbContext(builder.Options))
            {
                await context.Database.EnsureCreatedAsync();

                //ATTEMPT
                var book = NoSqlTestData.CreateDummyNoSqlBook();
                context.Add(book);
                await context.SaveChangesAsync();

                //VERIFY
                (await context.Books.CountAsync(p => p.BookId == book.BookId)).ShouldEqual(1);
            }
        }
        public bool UpdateNoSql(IImmutableList <BookChangeInfo> booksToUpdate)
        {
            if (_noSqlContext == null || !booksToUpdate.Any())
            {
                return(false);
            }

            foreach (var bookToUpdate in booksToUpdate)
            {
                switch (bookToUpdate.State)
                {
                case EntityState.Deleted:
                {
                    var noSqlBook = _noSqlContext.Find <BookListNoSql>(bookToUpdate.BookId);
                    _noSqlContext.Remove(noSqlBook);
                    break;
                }

                case EntityState.Modified:
                {
                    //Note: You need to read the actual Cosmos entity because of the extra columns like id, _rid, etc.
                    //Version 3 might make attach work https://github.com/aspnet/EntityFrameworkCore/issues/13633
                    var noSqlBook = _noSqlContext.Find <BookListNoSql>(bookToUpdate.BookId);
                    var update    = _sqlContext.Set <Book>()
                                    .ProjectTo <BookListNoSql>(SqlToNoSqlMapper)
                                    .Single(x => x.BookId == bookToUpdate.BookId);
                    SqlToNoSqlMapper.CreateMapper().Map(update, noSqlBook);
                    break;
                }

                case EntityState.Added:
                    var newBook = _sqlContext.Set <Book>()
                                  .ProjectTo <BookListNoSql>(SqlToNoSqlMapper)
                                  .Single(x => x.BookId == bookToUpdate.BookId);
                    _noSqlContext.Add(newBook);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            return(true);
        }
        public bool UpdateNoSql(IImmutableList <BookChangeInfo> booksToUpdate)
        {
            if (_noSqlContext == null || !booksToUpdate.Any())
            {
                return(false);
            }

            foreach (var bookToUpdate in booksToUpdate)
            {
                switch (bookToUpdate.State)
                {
                case EntityState.Deleted:
                {
                    var noSqlBook = _noSqlContext.Find <BookListNoSql>(bookToUpdate.BookId);
                    _noSqlContext.Remove(noSqlBook);
                    break;
                }

                case EntityState.Modified:
                {
                    var noSqlBook = _noSqlContext.Find <BookListNoSql>(bookToUpdate.BookId);
                    var update    = _sqlContext.Set <Book>()
                                    .ProjectTo <BookListNoSql>(SqlToNoSqlMapper)
                                    .Single(x => x.BookId == bookToUpdate.BookId);
                    SqlToNoSqlMapper.CreateMapper().Map(update, noSqlBook);
                    break;
                }

                case EntityState.Added:
                    var newBook = _sqlContext.Set <Book>()
                                  .ProjectTo <BookListNoSql>(SqlToNoSqlMapper)
                                  .Single(x => x.BookId == bookToUpdate.BookId);
                    _noSqlContext.Add(newBook);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            return(true);
        }
        public async Task TestCosmosDbCatchFailedRequestOk()
        {
            //SETUP
            var config  = AppSettings.GetConfiguration();
            var builder = new DbContextOptionsBuilder <NoSqlDbContext>()
                          .UseCosmos(
                config["endpoint"],
                config["authKey"],
                "UNKNOWNDATABASE");

            using (var context = new NoSqlDbContext(builder.Options))
            {
                //ATTEMPT
                var book = NoSqlTestData.CreateDummyNoSqlBook();
                context.Add(book);
                var ex = await Assert.ThrowsAsync <CosmosException>(async() => await context.SaveChangesAsync());

                //VERIFY
                ex.Message.ShouldStartWith("Response status code does not indicate success: 404 Substatus:");
            }
        }
        public async Task TestCosmosDbCatchFailedRequestOk()
        {
            //SETUP
            var config  = AppSettings.GetConfiguration();
            var builder = new DbContextOptionsBuilder <NoSqlDbContext>()
                          .UseCosmos(
                config["endpoint"],
                config["authKey"],
                "UNKNOWNDATABASE");

            using (var context = new NoSqlDbContext(builder.Options))
            {
                //ATTEMPT
                var book = NoSqlTestData.CreateDummyNoSqlBook();
                context.Add(book);
                var ex = await Assert.ThrowsAsync <HttpException>(async() => await context.SaveChangesAsync());

                //VERIFY
                ex.Message.ShouldEqual("NotFound");
            }
        }
        public async Task TestCosmosDbLocalDbEmulatorCreateDatabaseOk()
        {
            //SETUP
            var config  = AppSettings.GetConfiguration();
            var builder = new DbContextOptionsBuilder <NoSqlDbContext>()
                          .UseCosmos(
                config["endpoint"],
                config["authKey"],
                GetType().Name);

            using (var context = new NoSqlDbContext(builder.Options))
            {
                await context.Database.EnsureCreatedAsync();

                //ATTEMPT
                var book = NoSqlTestData.CreateDummyNoSqlBook();
                context.Add(book);
                await context.SaveChangesAsync();

                //VERIFY
                context.Books.Find(book.BookId).ShouldNotBeNull();
            }
        }
        public async Task TestCosmosDbLocalDbEmulatorCreateDatabaseOk()
        {
            //SETUP
            var config  = AppSettings.GetConfiguration();
            var builder = new DbContextOptionsBuilder <NoSqlDbContext>()
                          .UseCosmos(
                config["endpoint"],
                config["authKey"],
                nameof(TestNoSqlDbContext));

            using (var context = new NoSqlDbContext(builder.Options))
            {
                await context.Database.EnsureCreatedAsync();

                //ATTEMPT
                var book = NoSqlTestData.CreateDummyNoSqlBook();
                context.Add(book);
                await context.SaveChangesAsync();

                //VERIFY
                (await context.Books.CountAsync(p => p.BookId == book.BookId)).ShouldEqual(1);
            }
        }