public void Test_Can_Fetch_Eager_Load_Common(IRepository<Question> r)
        {
            var q = new Question { Text = "Hello", Answers = new List<Answer>(), Comments = new List<QuestionComment>() };
            var c = new QuestionComment { Question = q, Text = "Hei" };
            var a = new Answer { Question = q, Text = "Yes", Comments = new List<AnswerComment>() };

            q.Comments.Add(c);

            var ac = new AnswerComment { Answer = a, Text = "hahah" };
            a.Comments.Add(ac);

            q.Answers.Add(a);

            r.Save(q);

            r.Evict(q.QuestionId);

            var g = r.GetEager(q.QuestionId, "Answers", "Comments");

            Assert.AreEqual("Hello", g.Text);
            // System.Threading.Thread.Sleep(10000);
            Assert.AreEqual("Hei", g.Comments[0].Text);
            Assert.AreEqual("Yes", g.Answers[0].Text);
            Assert.AreEqual("hahah", g.Answers[0].Comments[0].Text);
        }
        void Common_Orm_SaveGraph_Can_Update(IRepository<Question> repo)
        {
            // Arrange
            Question importantQuestion = Refactored_Common_SaveGraph_Arrange_Create(repo);
            string expectedText = "number 9, number 9, number 9...";

            // Act
            int questionId = importantQuestion.QuestionId;
            byte[] rowVersion = importantQuestion.RowVersion;

            Question retrievedQuestion = repo.GetEager(questionId);

            int originalAnswersCount = retrievedQuestion.Answers.Count;
            // throw new Exception(retrievedQuestion.GetType().ToString());

            retrievedQuestion.Text = "Hello";
            retrievedQuestion.Answers.Single(x => x.Poster == "John").Text = expectedText;

            var z = retrievedQuestion.Answers.Single(x => x.Poster == "John");
            z.Text = expectedText;

            var a = retrievedQuestion.Answers.Single(x => x.Poster == "Paul");
            retrievedQuestion.Answers.Remove(a);

            repo.SaveGraph(retrievedQuestion); // save the whole object graph

            Question retrievedMergedQuestion = repo.GetEager(questionId);

            // Assert
            Assert.AreNotSame(importantQuestion, retrievedQuestion);
            Assert.AreNotSame(retrievedQuestion, retrievedMergedQuestion);

            Assert.AreEqual(expectedText, retrievedMergedQuestion.Answers.Single(x => x.Poster == "John").Text);
            Assert.AreEqual("Hello", retrievedMergedQuestion.Text);

            Assert.AreEqual(3, originalAnswersCount);
            Assert.AreEqual(2, retrievedMergedQuestion.Answers.Count);
        }
        void Common_Can_queue_changes(IRepository<Question> repo)
        {
            // Arrange
            Question importantQuestion = Refactored_Common_SaveGraph_Arrange_Create(repo);

            int questionId = importantQuestion.QuestionId;
            byte[] rowVersion = importantQuestion.RowVersion;

            /*
            Question retrievedQuestion;

            {
                var query = repo.All.Where(x => x.QuestionId == questionId);

                if (repo.All.Provider.GetType() == typeof(NHibernate.Linq.NhQueryProvider))
                {
                    retrievedQuestion = repo.Get(questionId);
                }
                else
                {
                    query = query.Include("Answers");
                    query = query.Include("Comments");
                    query = query.Include("Answers.Comments");
                    retrievedQuestion = query.Single();
                }
            }*/

            Question retrievedQuestion = repo.GetEager(questionId);

            retrievedQuestion.Text = "Hello";
            retrievedQuestion.Answers.Single(x => x.Poster == "John").Text = "number 9, number 9, number 9...";

            repo.Evict(questionId); // must Evict transient changes so it will not affect the next Save

            // Act
            repo.Save(new Question { Text = "Hi", Poster = "Optimus" });

            /*
            Question testConflicter;  // let's check if the two aggregate root didn't affect each other
            {
                var query = repo.All.Where(x => x.QuestionId == questionId);

                if (repo.All.Provider.GetType() == typeof(NHibernate.Linq.NhQueryProvider))
                {
                    testConflicter = repo.Get(questionId);

                    // throw new Exception(testConflicter.Text + " " + testConflicter.Comments.Single().Text);
                }
                else
                {
                    query = query.Include("Answers");
                    query = query.Include("Comments");
                    query = query.Include("Answers.Comments");
                    testConflicter = query.Single();
                }
            }
            */

            Question testConflicter = repo.GetEager(questionId);

            // Assert
            Assert.AreNotSame(importantQuestion, retrievedQuestion);
            Assert.AreNotSame(retrievedQuestion, testConflicter);

            Assert.AreEqual("The answer to life", testConflicter.Text);
            Assert.AreEqual("42", testConflicter.Answers.Single(x => x.Poster == "John").Text);

            Assert.AreEqual("Hello", retrievedQuestion.Text);

            /*
             Evicting the object from EF results on collections becoming empty, NHibernate left the stale object as is.

            throw new Exception(retrievedQuestion.Answers.Count.ToString()); // zero on Entity Framework after marking objects detached

            // Single won't work, there's no element
            Assert.AreEqual("number 9, number 9, number 9...", retrievedQuestion.Answers.Single(x => x.Poster == "John").Text);
            */
        }
        void Common_Can_Orm_SaveGraph_Can_Create(IRepository<Question> repo)
        {
            // Arrange
            Question importantQuestion = Refactored_Common_SaveGraph_Arrange_Create(repo);

            // Act
            int questionId = importantQuestion.QuestionId;
            byte[] rowVersion = importantQuestion.RowVersion;
            Question retrievedQuestion = repo.GetEager(questionId);

            // Assert
            Assert.IsNotNull(importantQuestion.RowVersion);
            Assert.AreNotEqual(0, importantQuestion.QuestionId);

            Assert.AreNotSame(importantQuestion, retrievedQuestion);

            Assert.IsNotNull(retrievedQuestion.RowVersion);
            Assert.AreEqual("The answer to life", retrievedQuestion.Text);

            Assert.IsNotNull(retrievedQuestion.Answers, "Answers not populated");
            CollectionAssert.AllItemsAreUnique(retrievedQuestion.Answers.Select(x => x.Poster).ToList());

            CollectionAssert.AreEqual(
                new string[] { "John", "Elton", "Paul" }.OrderBy(x => x).ToList(),
                retrievedQuestion.Answers.Select(x => x.Poster).OrderBy(x => x).ToList());

            CollectionAssert.AreNotEqual(
                new string[] { "John", "Paul" }.OrderBy(x => x).ToList(),
                retrievedQuestion.Answers.Select(x => x.Poster).OrderBy(x => x).ToList());

            CollectionAssert.AreNotEqual(
                new string[] { "John", "Yoko" }.OrderBy(x => x).ToList(),
                retrievedQuestion.Answers.Select(x => x.Poster).OrderBy(x => x).ToList());

            CollectionAssert.AreNotEqual(
                new string[] { "John", "Elton", "Paul", "Elvis" }.OrderBy(x => x).ToList(),
                retrievedQuestion.Answers.Select(x => x.Poster).OrderBy(x => x).ToList());

            Assert.AreEqual("George", retrievedQuestion.Comments.Where(x => x.Text == "Is There?").Single().Poster);

            Assert.AreEqual("Ringo", retrievedQuestion.Answers.Single(x => x.Poster == "Paul").Comments.Single().Poster);
        }
        void Common_CanSaveHeaderDetail_ThenHeaderOnly(IRepository<Product> db)
        {
            // NHibernate.ISession xxx = NhModelsMapper.GetSession(connectionString);

            // Arrange
            var px = new Product
            {
                ProductName = "Optimus",
                Category = "Autobots",
                MinimumPrice = 7
            };
            px.PriceList =
                new List<ProductPrice>()
                {
                    new ProductPrice { Product = px, Price = 777, EffectiveDate = DateTime.Today },
                    new ProductPrice { Product = px, Price = 888, EffectiveDate = DateTime.Today },
                    new ProductPrice { Product = px, Price = 999, EffectiveDate = DateTime.Today },
                    new ProductPrice { Product = px, Price = 222, EffectiveDate = DateTime.Today },

                };

            // Act
            db.SaveGraph(px);
            // xxx.Merge(px);

            byte[] rv = px.RowVersion;

            Assert.AreEqual(4, px.PriceList.Count());

            px = db.GetEager(px.ProductId);

            Assert.AreEqual("Optimus", px.ProductName);
            px.ProductName = px.ProductName + "?";
            px.PriceList[2].Price = 333;
            Assert.AreEqual(4, px.PriceList.Count);

            db.SaveGraph(px);

            Assert.AreNotEqual(0, px.ProductId);
            CollectionAssert.AreNotEqual(px.RowVersion, rv);

            // Assert

            Assert.AreEqual(px.ProductName, px.ProductName);
            Assert.AreNotEqual(0, px.ProductId);
            Assert.AreEqual(4, px.PriceList.Count);

            // Arrange

            Assert.AreNotEqual(0, px.ProductId);

            /* triggers concurrency exception
            byte[] x = px.RowVersion;
            x[0] += 1;
            px.RowVersion = x;
            */

            var py = new Product
            {
                ProductId = px.ProductId,
                ProductName = "Optimus",
                Category = "Autobotszx",
                MinimumPrice = 7,

                RowVersion = px.RowVersion

                // empty list is incompatible with cascade=all-delete-orphan
            };

            int pxid = px.ProductId;
            db.Save(py);

            Product pz = db.Get(px.ProductId);
            // throw new Exception(py.ProductId + " " + px.ProductId + " " + pxid);
            Assert.AreEqual(px.ProductId, py.ProductId);

            Assert.IsNotNull(pz.PriceList);
            Assert.AreEqual(4, pz.PriceList.Count);
        }
        void Common_CanSaveHeaderDetail(IRepository<Product> db)
        {
            // Arrange
            var px = new Product
            {
                ProductName = "Optimus",
                Category = "Autobots",
                MinimumPrice = 7
            };
            px.PriceList =
                new List<ProductPrice>()
                {
                    new ProductPrice { Product = px, Price = 777, EffectiveDate = DateTime.Today },
                    new ProductPrice { Product = px, Price = 888, EffectiveDate = DateTime.Today },
                    new ProductPrice { Product = px, Price = 999, EffectiveDate = DateTime.Today },
                    new ProductPrice { Product = px, Price = 222, EffectiveDate = DateTime.Today },

                };

            // Act
            db.SaveGraph(px);

            Assert.AreEqual(4, px.PriceList.Count());

            px = db.GetEager(px.ProductId);

            Assert.AreEqual("Optimus", px.ProductName);
            px.ProductName = px.ProductName + "!";
            px.PriceList[2].Price = 333;
            Assert.AreEqual(4, px.PriceList.Count);

            db.SaveGraph(px);

            // Assert

            Assert.AreEqual(px.ProductName, px.ProductName);
            Assert.AreEqual(px.ProductId, px.ProductId);
            Assert.AreEqual(4, px.PriceList.Count);
        }