1

I am using the BulkInsert operation of RavenDB 4.0.6 to insert a bunch of products:

    using (var bulk = Store.BulkInsert())
    {
        foreach (var p in products)
        {
            p.Id = string.Empty; // <-- notice this
            await bulk.StoreAsync(p);
        }
    }

Notice that I'm deliberately skipping the identifier creation strategy by explicitly providing string.Empty as the value of the Id property. This is based on the RavenDB docs, section Autogenerated ID's.

When running the code I get the error:

System.InvalidOperationException : Document id must have a non empty value

Which is directly produced by this codesnippet in BulkInsertOperation.cs.

My question is how I can prevent this error and still keep the same ID-generation strategy as my other code does?

E.g. I never set the Id property to anything other than string.Empty. And I'm afraid that setting it to, for example, Guid.NewGuid.ToString() might cause other issues (see this question as well).

Juliën
  • 9,047
  • 7
  • 49
  • 80

1 Answers1

2

For bulk operations, you have to either leave the Id property null (not empty string) to have it auto-generate a sequential ID, or generate a Guid ID manually.

The API is a bit inconsistent between bulk inserts and session inserts:

using (var store = new DocumentStore() { Urls = new[] { "http://localhost:8080" } }.Initialize())
{
  using (var bulk = store.BulkInsert("Sample"))
  {
    bulk.Store(new SampleDocument { Name = "Bulk.Store Null Id", Id = null }); // Sequential Id (I.E. SampleDocuments/1-A)
    bulk.Store(new SampleDocument { Name = "Bulk.Store Blank Id", Id = "" }); // Throws Error
    bulk.Store(new SampleDocument { Name = "Bulk.Store Guid Id", Id = Guid.NewGuid().ToString() }); // Guid Id
  }

  using (var session = store.OpenSession("Sample"))
  {
    session.Store(new SampleDocument { Name = "Session.Store Null Id", Id = null }); // Sequential Id (I.E. SampleDocuments/2-A)
    session.Store(new SampleDocument { Name = "Session.Store Empty Id", Id = "" }); // Guid Id
    session.Store(new SampleDocument { Name = "Session.Store Guid Id", Id = Guid.NewGuid().ToString() }); // Guid Id
    session.SaveChanges();
  }
}
Eric Damtoft
  • 1,353
  • 7
  • 13
  • Thanks, that confirms what I stated indeed. But `Guid.NewGuid().ToString()` does seem to have a different side-effect than relying on the `string.Empty`, see also the linked question at the end of my question. Which leads back to my actual question: what can be done to prevent this and keep the same identity strategy? – Juliën Sep 26 '18 at 14:09
  • I think the core problem is that for Load, type safety only persists for the session. It appears that regardless of the Id strategy, once you close the session, you lose the type safety. – Eric Damtoft Sep 26 '18 at 14:59
  • According to https://stackoverflow.com/a/49922425/4541880, `store.Query.Where(x => x.Id == id)` should both be performant and type safe, regardless of Id strategy – Eric Damtoft Sep 26 '18 at 15:00