protected Book makeBook()
 {
     var book = new Book() { Title = "The Hobbit" };
     db.Books.Add(book);
     save();
     return book;
 }
 public void ErrorIsThrownWhenTryingToMixTransactionSystems()
 {
     using (var transaction = db.Database.BeginTransaction())
     {
         var book = new Book() { Title = "Title" };
         db.Books.Add(book);
         Assert.Throws<ConflictingTransactionException>(() => db.Logger.SaveChanges(user));
         transaction.Rollback();
     }
 }
        public void FrameLogMakesUseOfDbContextTransaction()
        {
            Book book;
            var db2 = new ExampleContext();
            using (var transaction = db.Database.BeginTransaction())
            {
                book = new Book() { Title = "Title" };
                db.Books.Add(book);
                db.Logger.SaveChangesWithinExplicitTransaction(user);

                Assert.IsNull(db2.Books.SingleOrDefault(b => b.Id == book.Id));
                transaction.Commit();
            }
            Assert.IsNotNull(db2.Books.SingleOrDefault(b => b.Id == book.Id));
        }
        public void CustomSaveChangesThatLinksAnUnattachedObjectWillBeLoggedWithTheCorrectRelationshipReferences()
        {
            // Arrange...
            var howToLearnFrenchPart1 = new Book() { Title = HowToLearnFrenchPart1 };

            // Act...
            db.Books.Add(howToLearnFrenchPart1);
            save();

            // Assert...
            var changeSet = lastChangeSet();
            var frenchPart1ObjectChange = changeSet.ObjectChanges.FirstOrDefault(x => x.PropertyChanges.Any(y => y.PropertyName == "Title" && y.Value == HowToLearnFrenchPart1));
            var frenchPart2ObjectChange = changeSet.ObjectChanges.FirstOrDefault(x => x.PropertyChanges.Any(y => y.PropertyName == "Title" && y.Value == HowToLearnFrenchPart2));
            Assert.IsNotNull(frenchPart1ObjectChange, "Expected changes to be logged for french (part 1), but there were none");
            Assert.IsNotNull(frenchPart2ObjectChange, "Expected changes to be logged for french (part 2), but there were none");
            Assert.IsNotNull(howToLearnFrenchPart1.Sequel, "Expected sequal to be created for french (part 1) during save changes, but it was not");
            Assert.AreEqual(howToLearnFrenchPart1.Id.ToString(), frenchPart1ObjectChange.ObjectReference, "Actual object reference for french (part 1) does not match the logged reference");
            Assert.AreEqual(howToLearnFrenchPart1.Sequel.Id.ToString(), frenchPart2ObjectChange.ObjectReference, "Actual object reference for french (part 1) does not match the logged reference");
            var frenchPart1SequalPropertyChange = frenchPart1ObjectChange.PropertyChanges.FirstOrDefault(x => x.PropertyName == "Sequel");
            Assert.IsNotNull(frenchPart1SequalPropertyChange, "Expected property change for the 'Sequel' of french (part 1), but there was none");
            Assert.AreEqual(frenchPart2ObjectChange.ObjectReference, frenchPart1SequalPropertyChange.Value, "Actual object reference for french (part 2 ) does not match the logged reference in 'Sequal' property of french (part 1)");
        }
        public void CustomSaveChangesThatTriggersAnExceptionWillNotPersistTheChanges()
        {
            // Arrange...
            // NOTE: 1 million fans will trigger an overflow exception on save (see customSaveChanges() below)
            var book = new Book()
            {
                Title = "How to be really popular",
                NumberOfFans = 1000000
            };

            // Act...
            db.Books.Add(book);

            // Assert...
            var ex = Assert.Throws<OverflowException>(() => save(), "Expected the book to trigger an overflow exception, but it didn't");
            Assert.AreEqual(0, book.Id, "Expected that the book would not be assigned an id, but it was the id of \"{0}\"", book.Id);
        }
        public void CustomSaveChangesThatModifiesAnUnchangedPropertyOfAnUnchangedObjectWillBeLogged()
        {
            // Arrange...
            var howToLearnFrenchPart1 = new Book() { Title = HowToLearnFrenchPart1 };

            // Act...
            db.Books.Add(howToLearnFrenchPart1);
            save();

            // Assert...
            var changeSet = lastChangeSet();
            var frenchPart1ObjectChange = changeSet.ObjectChanges.FirstOrDefault(x => x.PropertyChanges.Any(y => y.PropertyName == "Title" && y.Value == HowToLearnFrenchPart1));
            var frenchPart2ObjectChange = changeSet.ObjectChanges.FirstOrDefault(x => x.PropertyChanges.Any(y => y.PropertyName == "Title" && y.Value == HowToLearnFrenchPart2));
            Assert.IsNotNull(frenchPart1ObjectChange, "Expected changes to be logged for french (part 1), but there were none");
            Assert.IsNotNull(frenchPart2ObjectChange, "Expected changes to be logged for french (part 2), but there were none");
        }
 public void NoErrorIsThrownIfExplicitTransactionIsPassedToFrameLog()
 {
     using (var transaction = db.Database.BeginTransaction())
     {
         var book = new Book() { Title = "Title" };
         db.Books.Add(book);
         Assert.DoesNotThrow(() => db.Logger.SaveChangesWithinExplicitTransaction(user));
         transaction.Rollback();
     }
 }
        /// <summary>
        /// We check that the changes that FrameLog makes to the database are really
        /// wrapped in the transaction scope we wrapped the save changes call in.
        /// 
        /// We do this by, during the transaction, opening a new transaction scope
        /// with TransactionScopeOption.Suppress. This means that the code inside
        /// this scope takes place outside the current transaction.
        /// </summary>
        private void checkTransactionScope(TransactionOptions options)
        {
            Book book = new Book() { Title = "Title" };

            using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
            {
                db.Books.Add(book);
                db.Logger.SaveChanges(user, options);

                using (var outsideTransaction = new TransactionScope(TransactionScopeOption.Suppress))
                {
                    // We can't see the change from outside the transaction
                    Assert.IsNull(db.Books.SingleOrDefault(b => b.Id == book.Id));
                }
                transaction.Complete();
            }
            Assert.IsNotNull(db.Books.SingleOrDefault(b => b.Id == book.Id));
        }
 private bool compare(Book a, Book b)
 {
     return a.Title == b.Title
         && a.NumberOfFans == b.NumberOfFans
         && a.Sequel == b.Sequel
         && a.Style.Hardcover == b.Style.Hardcover;
 }