2

I have the following test case that i expect to pass. But it does not pass with RavenDB.
If i create the exact same test with MsSql, it does pass.

        var connectionString = "Url=http://localhost:8080";
        var store = new DocumentStore();
        store.ParseConnectionString(connectionString);
        store.Initialize();
        using (var scope = new TransactionScope())
        using (var session = store.OpenSession())
        {
            session.Store(dog);
            session.SaveChanges();

            var dogs = session.Query<Dog>().Customize(x => x.WaitForNonStaleResults()).ToList();
            Assert.AreEqual(1, dogs.Count);
            scope.Complete();
        }

I am trying to write some code that works the same, not matter what database i choose, and this is just an example of a test case i am trying to get to pass.

I have tried various things, such as waitfornonstaleresults, and allownonauthetitative..something, etc etc.

Quintonn
  • 770
  • 8
  • 29
  • So I can't do a query before the transaction completes, ok (for now). I created a different test, where i make a call to RavenDB and a call to MsSql inside the same transaction. But it throws an exception. Here's a link to that question: http://stackoverflow.com/questions/24828095/ravendb-and-mssql-inside-same-transaction-scope-results-in-webexception – Quintonn Jul 18 '14 at 15:01

2 Answers2

6

To expand on Ayende's answer, unlike MSSQL, the Document Store (Store/Load operations) is separate from the Index Store and is the only thing that is ACID. The Index Store is not transactional, and is updated asynchronously after the update to the document store is finished. In this case, using a distributed (DTC) transaction, after the transaction has committed. This is by design.

Therefore, while your code will not work as you intend, this should:

var connectionString = "Url=http://localhost:8080";
var store = new DocumentStore();
store.ParseConnectionString(connectionString);
store.Initialize();
using (var scope = new TransactionScope())
using (var session = store.OpenSession())
{
    Dog dog = new Dog { Id = "dogs/1" };
    session.Store(dog);
    session.SaveChanges();

    var dog2 = session.Load<Dog>("dogs/1");
    Assert.AreEqual(dog, dog2);
    scope.Complete();
}

You may even be able to use:

Dog[] dogs = session.Advanced.LoadStartingWith<Dog>("dogs");

But anything asking for data from the index store (a Query) will not return because the data hasn't even been permanently added to the transactional store yet, much less asynchronously mapped into the index store.

David Boike
  • 18,545
  • 7
  • 59
  • 94
2

In RavenDB, until the DTC transaction has been committed, the data will not be added to any indexes.

Ayende Rahien
  • 22,925
  • 1
  • 36
  • 41
  • Is there any way to get this to work? Any way at all? – Quintonn Jul 15 '14 at 06:17
  • You haven't understood the true nature of RavenDB. The data and the indexes does not work in the same thread. Think of the indexes as cache tables in SQL. When you change the data, there's a trigger which starts updating the cache table with the data. This means that you have to commit the data first(scope.complete), then wait for the index to be done updating. ofc you can always just do a session.load(), that will always give you the correct data – Michael Kire Hansen Sep 10 '15 at 09:06
  • Also note that you can do a session.load() on a list of id's, not just a single id. – Michael Kire Hansen Sep 10 '15 at 09:10