Get Document ID before SaveChanges

569 views
Skip to first unread message

James Hancock

unread,
Feb 4, 2013, 6:11:52 PM2/4/13
to rav...@googlegroups.com
I have a sharded store and I have a session and an object that is about to be stored in the session and then saved.

However I need to create several other documents before the save occurs and those other documents must reference the first. (journal entries that are their own documents referencing a transaction)

So I need to get a new document ID before the save happens.

I thought I saw a GenerateDocumentID function somewhere but I can't find it.

How do I go about generating a new Id before storage?

Thanks!

Matt Warren

unread,
Feb 4, 2013, 6:38:57 PM2/4/13
to ravendb
RavenDB will actually give you an Id as soon as you call Store(), to support this exact scenario.

In fact, you should see it written back into your POCO object, so you can do something like this:
    session.Store(objA);
    objB.Link = objA.Id;
    session.Store(objB);
    session.SaveChanges();



--
You received this message because you are subscribed to the Google Groups "ravendb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Matt Johnson

unread,
Feb 4, 2013, 6:45:53 PM2/4/13
to rav...@googlegroups.com
As Matt W. said, the new document id is available as soon as you store the object in the session.  You can simply get the Id property back from your own entity.

The method you were thinking of is DocumentStore.Conventions.GenerateDocumentKey() - but usually you don't need to call it directly.

There are a few use cases where you might want it though.  One use case is in a CQRS architecture, in which case you would just be reserving an Id to send with a command, but not necessarily using it right away.  There's an extension method for this in the Raven.Contrib project here:  

James Hancock

unread,
Feb 5, 2013, 9:32:32 AM2/5/13
to rav...@googlegroups.com
I can confirm that:
 
session.Store(someobject) is not assigning an ID while in sharding mode. It does work if I disable sharding.
 
James Hancock
 

James Hancock

unread,
Feb 5, 2013, 9:35:20 AM2/5/13
to rav...@googlegroups.com
(Trying to work around this issue)
 
I see that Generate document store takes a database name (which should be known by the store I would think?) and database commands (which again should be known by the store? )
 
How do I fill these in when I have the session, and the store for a sharded database?
 
 
James Hancock
 

James Hancock

unread,
Feb 5, 2013, 9:52:01 AM2/5/13
to rav...@googlegroups.com
Also, this fails:
 

this.Id = await session.Advanced.DocumentStore.Conventions.GenerateDocumentKeyAsync(session.Advanced.DocumentStore.Identifier, session.Advanced.DocumentStore.AsyncDatabaseCommands, this);

Matt Johnson

unread,
Feb 5, 2013, 10:34:23 AM2/5/13
to rav...@googlegroups.com
James, can you please create a Gist with a failing unit test and log a bug on http://issues.hibernatingrhinos.com

Thanks

James Hancock

unread,
Feb 5, 2013, 10:41:03 AM2/5/13
to rav...@googlegroups.com
I actually have a shorter test case for you. It fails on any async session. 

[TestMethod]

 

public void TestIdOnStore()

 

{

 

using (var store = NewDocumentStore())

 

{

 

using (var session = store.OpenAsyncSession())

 

{

 

var account = new TestAccount(TestAccountTypes.BankAccount, "Test", "123");

 

session.Store(account);

 

System.Diagnostics.Debug.Assert(string.IsNullOrWhiteSpace(session.Advanced.GetDocumentId(account)));

 

}

 

}

 

}

 
This will never assert.
 
Doesn’t matter what TestAccount is, could be just a class with one property.
 
 
 
 
James Hancock
 
From: Matt Johnson
Sent: ‎February‎ ‎5‎, ‎2013 ‎10‎:‎34‎ ‎AM
To: rav...@googlegroups.com
Subject: Re: [RavenDB] Get Document ID before SaveChanges
 

Matt Johnson

unread,
Feb 5, 2013, 11:02:50 AM2/5/13
to rav...@googlegroups.com
Interesting.  I don't know enough about the async API to know if this is desired behavior or not.

However, I can offer you a solution.  You tried this without success:
this.Id = await session.Advanced.DocumentStore.Conventions.GenerateDocumentKeyAsync(session.Advanced.DocumentStore.Identifier, session.Advanced.DocumentStore.AsyncDatabaseCommands, this);

Try this instead:

var realSession = (AsyncDocumentSession) session;
await session.Advanced.DocumentStore.Conventions.GenerateDocumentKeyAsync(realSession.DatabaseName, realSession.AsyncDatabaseCommands, yourEntity);

Note that by awaiting the operation, you are loosing some of the asynchronousness.  It may have to touch the database to get the hi/lo values.  But it should work. 

James Hancock

unread,
Feb 5, 2013, 11:13:37 AM2/5/13
to rav...@googlegroups.com
Thanks for the suggestion. Doesn’t work with a sharded session even if I adapt the code because I can’t get database commands for it.
 
James Hancock
 
From: Matt Johnson
Sent: ‎February‎ ‎5‎, ‎2013 ‎11‎:‎03‎ ‎AM
To: rav...@googlegroups.com
Subject: Re: [RavenDB] Get Document ID before SaveChanges
 

James Hancock

unread,
Feb 5, 2013, 11:28:45 AM2/5/13
to rav...@googlegroups.com
I got this to work:
 

this.Id = await realSession.Conventions.GenerateDocumentKeyAsync(realSession.DatabaseName, ((ShardedDocumentStore)realSession.DocumentStore).ShardStrategy.Shards[SourceContact.ShardLocation].AsyncDatabaseCommands, this);

I was able to do this because I knew the shard based on the contact’s shard where the transaction should also be on the same shard.
 
The problem is that this returns an id without the shard information on it.
 
Worse, if you tack it on, so that your references can be accurate, then when you actually save it to the database, it tacks on the shard again, so you end up with duplicates.
 
Really really really need the AsyncDocumentSession.Store() to assign a proper ID with the shard information on it so that this can work.  Bug happens with or without sharding.
 
James Hancock
 
From: James Hancock
Sent: ‎February‎ ‎5‎, ‎2013 ‎11‎:‎13‎ ‎AM
To: rav...@googlegroups.com
Subject: RE: [RavenDB] Get Document ID before SaveChanges
 

Oren Eini (Ayende Rahien)

unread,
Feb 5, 2013, 12:21:17 PM2/5/13
to ravendb
James,
As we discussed on the other post, this isn't a sharding issue.
This is by design behavior for async sessions.

James Hancock

unread,
Feb 5, 2013, 12:24:28 PM2/5/13
to rav...@googlegroups.com
However, the issue is made worse because when sharding you have no way of getting the full Id per below.
 
Thus it’s an async issue with a compounding GenerateDocumentKeyAsync issue.
 
James Hancock
 

Oren Eini (Ayende Rahien)

unread,
Feb 5, 2013, 12:40:24 PM2/5/13
to ravendb
Huh?

This prints: two/users/1

using (var store = new ShardedDocumentStore(new ShardStrategy(new Dictionary<string, IDocumentStore>
{
{"one", new DocumentStore{Url = "http://localhost:8080"}},
{"two", new DocumentStore{Url = "http://remotehost:8080"}},
})).Initialize())
{
using (var session = store.OpenSession())
{
var user = new User();
session.Store(user);
Console.WriteLine(user.Id);
}
}

James Hancock

unread,
Feb 5, 2013, 1:02:42 PM2/5/13
to rav...@googlegroups.com
BUT IT DOESN’T WORKING ASYNCHRONOUSLY!!!!!!!!!!!!
 
You’re running around in circles. The point is that you can’t get it async without saving to the database, and you can’t manually get it async either if you’re sharding.
 
Show me a way to get the full ID with shard information from an async session without having to SaveChangesAsync() first.

Oren Eini (Ayende Rahien)

unread,
Feb 5, 2013, 1:04:40 PM2/5/13
to ravendb
Please don't shout.
Please note the title of your post.

Sharding & ids works just fine.
Your problem is with async session.

I understand that you don't like the current behavior, but it isn't a bug. It is behaving this way because it is designed this way.
If you feel so strongly about it, please send us a pull request. 

James Hancock

unread,
Feb 5, 2013, 1:30:54 PM2/5/13
to rav...@googlegroups.com
I am just looking for a non-cicular answer to a simple question:
 
How do I get a fully formed ID from a sharded database with an async session before save?
 
That’s all I need. What I keep getting is a circular reference pointing to one solution or another and they all have different issues that prevent them from working.
 
Worse, the solution that should work, and does work every other way, doesn’t work in this one, which is a BUG.
 
When my staff does this sort of things it’s because they’re evading my question because they don’t want to answer it. 
 
I’m deciding if I’ve wasted 2 weeks of my life and time porting an app to Raven or not. If I choose not, then over the next year, Raven stands to sell to my company $100,000 worth of licenses or more. (could be easily more) And that would be recurring revenue.
 
But I won’t risk my company on getting excuses and non-answers to questions.
 
Tell me now if you want my business or not. If you do, then I need real answers to my issues with references, and a real answer to this question, and any others that I encounter.
 
If not, tell me so I can go spend my time doing something useful instead of beating my head against a wall and being rewarded with evasion.

Oren Eini (Ayende Rahien)

unread,
Feb 5, 2013, 1:46:17 PM2/5/13
to ravendb
inline


On Tue, Feb 5, 2013 at 8:30 PM, James Hancock <jr...@outlook.com> wrote:
I am just looking for a non-cicular answer to a simple question:
 
How do I get a fully formed ID from a sharded database with an async session before save?

Currently, you don't. That is by design.
If you really need that, you can either call SaveChangesAsync or send a pull request for the issue I pointed you to.
 
 
That’s all I need. What I keep getting is a circular reference pointing to one solution or another and they all have different issues that prevent them from working.
 
Worse, the solution that should work, and does work every other way, doesn’t work in this one, which is a BUG.

It is not a bug. That is the way it was designed to work.
 
 
When my staff does this sort of things it’s because they’re evading my question because they don’t want to answer it. 
 
I’m deciding if I’ve wasted 2 weeks of my life and time porting an app to Raven or not. If I choose not, then over the next year, Raven stands to sell to my company $100,000 worth of licenses or more. (could be easily more) And that would be recurring revenue.
 
But I won’t risk my company on getting excuses and non-answers to questions.
 
Tell me now if you want my business or not. If you do, then I need real answers to my issues with references, and a real answer to this question, and any others that I encounter.

We have been answering your questions. And quite rapidly, too.
If you want an escalated support channel, we have both Priority and Enterprise support channels available for you.
For what it worth, priority support will get you priority to resolve that bug internally, instead of waiting for a pull request.
It is the difference between being a paying customer and just another guy in the free community mailing list.
 
 
If not, tell me so I can go spend my time doing something useful instead of beating my head against a wall and being rewarded with evasion.
 

I don't follow. We are being quite forthright here, I don't recall any evasiveness.

devm...@hotmail.com

unread,
Feb 5, 2013, 1:56:11 PM2/5/13
to rav...@googlegroups.com
@James Hancock 

relax man, RavenDB is really great and helpful, not to mention that you are getting answers from the Creator of this software (Ayende) and he does provide great answers

i am not one of the team, i am just a user, and i can tell you that RavenDB is used in big serious enterprise projects.

RavenDB is so flexible and there is always a solution for a problem, if not the team will make a solution if there is a pull request, which is how any software requests implementation works


as for the licenses , well from my experience and i think others would share this too, RavenDB will save you nightmares and days of crazy SQL Server work flow, so your company and co workers will be very glad at the end.

as a friendly advise just go through the manual again, and always ask here, and most defiantly you will get a satisfying answers just help the team to understand your problem and e little patiant .

peace

James Hancock

unread,
Feb 5, 2013, 2:21:32 PM2/5/13
to rav...@googlegroups.com
I was just told that this is by design and there is no work around.
 
Thus your statements are incorrect. I run a bank. I don’t have the luxury of waiting weeks as if it was a hobby project to get fixes or get issues addressed. Since I started testing raven, I’ve reported 9 bugs, and 3 usability issues. 4 of the bugs have been fixed. Of those 9 bugs, I was asked to create repro cases for something that was broken out of the box (i.e. the issue with getting the document ID on async.) at least 3 times thus wasting more of my time.
 
I was further told that I have to spend money to get support for a product that I have yet to be convinced can actually work because of known issues. Sorry but I don’t work that way nor will I allow my company to work that way.
 
And quite honestly, if you’re using SQL Server correctly and denormalizing where appropriate, which we were already doing, our load tests show no improvement between Raven and SQL server for speed or scalability. The sole benefit was that we got sharding automatically. (in fact, put in 1 million records and watch all of the stale indexes all over the place, which is 100% not acceptable in an accounting scenario, and is not “safe by design” as advertised.
 
The reality is that any marginally complex structure where documents are self-referencing etc. Raven is actually incredibly hostile, and there is no indication that Raven developers are at all interested in addressing this - They’re actually proud of their system that is less capable than essentially any other solution in most complex structures. i.e. I got told that a standard Accounting structure with contacts, accounts , journal entries and transactions was complex, even though it was the second thing after a task manager that people tried to solve using computers back with 2 k of memory. My personal favorite was when I was told to store millions of journal entries and hundreds of accounts in a single document with a contact, and then told that I was doing it wrong when I asked how the transaction could then go and reference the journal entries it created.
 
I have been more than patient. I’ve spun questions around a thousand different ways. I’ve endured the “You’re a stupid RDMS guy, go read the docs again and try and get your head out of your A$$” comments like below over and over again, and when asked what I’m doing wrong with my structure, no one can or would give me an answer on what I was doing wrong. (the secret is that I wasn’t doing anything wrong with my structure and I fully understand document stores and my comments were valid, but people were unwilling to address the problems because they were too busy feeling superior as if storing json text documents on the file system was some revolution that others hadn’t tried already - XML databases from the 90s anyone?)
 
Raven has some great technologies. The way sharding is done is fantastic for instance. The concept of the document store can work well, if it also allows for the recognition that data isn’t independent and must allow referencing sometimes internal referencing and must be able to get that information quickly and easily.  It also has some major issues, such as Lucene indexes updating in the background which causes integrity issues or timeouts or both with stale indexes etc.  And I was willing to live with those and find work arounds for those issues, but what I’m not willing to do is risk my company on a group of people that think that they’ve created perfection and as one blog post put it “As per usual, if it isn’t working in Raven, then you’re doing it wrong.”   (paraphrasing but you get the gist) instead of saying “We have some really great technology that is relatively immature compared to other established solutions. Hang with us and we’ll work hard to fill in the gaps and listen to your issues and scenarios and work with you to find an existing solution, or code something in. The later is correct approach to business. The former, which I should have realized would be the case but hoped for the best thinking that it was mostly marketing bravado, is what is written all over everything on the Raven site.
 
So sorry, unacceptable answers.  Too bad too. Could have been highly profitable for all involved. Now I get to write what I was avoiding before. An SQL Server sharding engine.
 
James Hancock
 
From: devm...@hotmail.com
Sent: ‎February‎ ‎5‎, ‎2013 ‎1‎:‎56‎ ‎PM
To: rav...@googlegroups.com
Subject: Re: [RavenDB] Get Document ID before SaveChanges
 
--

Khalid Abuhakmeh

unread,
Feb 5, 2013, 2:24:11 PM2/5/13
to rav...@googlegroups.com
Stepping back for a second. Is the Store method on a session really going to bottle neck your API / Web application?

I always assumed the AsyncDocumentSession was for running multiple queries, which the Lazily feature of RavenDB can do as well.

Matt Johnson

unread,
Feb 5, 2013, 3:01:17 PM2/5/13
to rav...@googlegroups.com
Also, I know the guidance is to avoid them, but perhaps this is a reasonable use case for Guid identifiers?  Sharding aside - if you want a pure async response, you can't hit the database ahead of time to get a hilo key without being synchronous in some minor way.  Add sharding in the mix, and there's the question of which shard to hit in order to retrieve the proper hilo sequence.  So as ugly as they may be - I might be inclined to use a Guid Id in this scenario.

James Hancock

unread,
Feb 5, 2013, 3:18:11 PM2/5/13
to rav...@googlegroups.com
It won’t if it’s async and will return the ID. But there isn’t an async version and thus cannot get the id, and thus the point is moot.
 
 
 
James Hancock
 
From: Khalid Abuhakmeh
Sent: ‎February‎ ‎5‎, ‎2013 ‎2‎:‎24‎ ‎PM
To: rav...@googlegroups.com
Subject: Re: [RavenDB] Get Document ID before SaveChanges
 
Stepping back for a second. Is the Store method on a session really going to bottle neck your API / Web application?

I always assumed the AsyncDocumentSession was for running multiple queries, which the Lazily feature of RavenDB can do as well.

On Tuesday, February 5, 2013 1:56:11 PM UTC-5, devm...@hotmail.com wrote:
@James Hancock 

relax man, RavenDB is really great and helpful, not to mention that you are getting answers from the Creator of this software (Ayende) and he does provide great answers

i am not one of the team, i am just a user, and i can tell you that RavenDB is used in big serious enterprise projects.

RavenDB is so flexible and there is always a solution for a problem, if not the team will make a solution if there is a pull request, which is how any software requests implementation works


as for the licenses , well from my experience and i think others would share this too, RavenDB will save you nightmares and days of crazy SQL Server work flow, so your company and co workers will be very glad at the end.

as a friendly advise just go through the manual again, and always ask here, and most defiantly you will get a satisfying answers just help the team to understand your problem and e little patiant .

peace

 

--

James Hancock

unread,
Feb 5, 2013, 3:18:57 PM2/5/13
to rav...@googlegroups.com
We use GUIDs on SQL, but it wouldn’t matter with sharding because the shard is part of the ID, and needs to be determined. You can’t just create a magic ID in this case.
 
James Hancock
 
From: Matt Johnson
Sent: ‎February‎ ‎5‎, ‎2013 ‎3‎:‎01‎ ‎PM
To: rav...@googlegroups.com
Subject: Re: [RavenDB] Get Document ID before SaveChanges
 
Also, I know the guidance is to avoid them, but perhaps this is a reasonable use case for Guid identifiers?  Sharding aside - if you want a pure async response, you can't hit the database ahead of time to get a hilo key without being synchronous in some minor way.  Add sharding in the mix, and there's the question of which shard to hit in order to retrieve the proper hilo sequence.  So as ugly as they may be - I might be inclined to use a Guid Id in this scenario.


On Tuesday, February 5, 2013 12:24:11 PM UTC-7, Khalid Abuhakmeh wrote:
Stepping back for a second. Is the Store method on a session really going to bottle neck your API / Web application?

I always assumed the AsyncDocumentSession was for running multiple queries, which the Lazily feature of RavenDB can do as well.

On Tuesday, February 5, 2013 1:56:11 PM UTC-5, devm...@hotmail.com wrote:
@James Hancock 

relax man, RavenDB is really great and helpful, not to mention that you are getting answers from the Creator of this software (Ayende) and he does provide great answers

i am not one of the team, i am just a user, and i can tell you that RavenDB is used in big serious enterprise projects.

RavenDB is so flexible and there is always a solution for a problem, if not the team will make a solution if there is a pull request, which is how any software requests implementation works


as for the licenses , well from my experience and i think others would share this too, RavenDB will save you nightmares and days of crazy SQL Server work flow, so your company and co workers will be very glad at the end.

as a friendly advise just go through the manual again, and always ask here, and most defiantly you will get a satisfying answers just help the team to understand your problem and e little patiant .

peace

Oren Eini (Ayende Rahien)

unread,
Feb 5, 2013, 3:31:02 PM2/5/13
to ravendb
inline


On Tue, Feb 5, 2013 at 9:21 PM, James Hancock <jr...@outlook.com> wrote:
I was just told that this is by design and there is no work around.
 

Yes, which is the actual answer. There is no evasion there. By design, Store in async session won't get you an id.
You might not like it, but it isn't the same as a bug.

 
Thus your statements are incorrect. I run a bank. I don’t have the luxury of waiting weeks as if it was a hobby project to get fixes or get issues addressed. Since I started testing raven, I’ve reported 9 bugs, and 3 usability issues. 4 of the bugs have been fixed. Of those 9 bugs, I was asked to create repro cases for something that was broken out of the box (i.e. the issue with getting the document ID on async.) at least 3 times thus wasting more of my time.

James,
To be frank, you are using the community support option. You aren't a customer. While we would like you to be a customer, you have to set your expectations accordingly.
Right now, from our perspective, you are a random guy off the street coming up and saying: "I have a problem".
It is actually helpful to know _what the problem is_. We treat support very seriously, and we are trying to provide great support even for people who aren't customers.
That said, there are priorities in place, and if I have to spend an hour trying to figure out what you meant or work on a paying customer's support ticket or do some feature / bugs, you can guess what I am going to choose.

When you actually did provide failing tests, it was usually fixed in a matter of hours. 
I challenge you to find any other company where you would get this level of support, responsiveness and turn around time that you get from us. Again, this isn't to a paying customer, this is for some guy off the street.
We take a lot of pride in the quality of our support.

If you want us to actually do investigative work for you, we would be happy to. But that requires us to be a paying customer.  
 
I was further told that I have to spend money to get support for a product that I have yet to be convinced can actually work because of known issues. Sorry but I don’t work that way nor will I allow my company to work that way.

Allow me to give you the other side: I was further told that I am expected to do unpaid psychic debugging on some random person. Sorry, but I work that way only up to a point. 
 
 
 
The reality is that any marginally complex structure where documents are self-referencing etc. Raven is actually incredibly hostile, and there is no indication that Raven developers are at all interested in addressing this - They’re actually proud of their system that is less capable than essentially any other solution in most complex structures. i.e. I got told that a standard Accounting structure with contacts, accounts , journal entries and transactions was complex, even though it was the second thing after a task manager that people tried to solve using computers back with 2 k of memory. My personal favorite was when I was told to store millions of journal entries and hundreds of accounts in a single document with a contact, and then told that I was doing it wrong when I asked how the transaction could then go and reference the journal entries it created.
 

I think that you are confusing things. This is a public mailing list, made out of the people in the community.
If you post here, you get opinions from a lot of people. If you want to have actual advice about your software, from Hibernating Rhinos or its affiliates, we have channels available for that. 
And yes, they are open for paying customers.
 
I have been more than patient.

No, you have not. I am not sure if you are aware of that, but your tune has been anything but.

 
I’ve spun questions around a thousand different ways. I’ve endured the “You’re a stupid RDMS guy, go read the docs again and try and get your head out of your A$$” comments like below over and over again, and when asked what I’m doing wrong with my structure, no one can or would give me an answer on what I was doing wrong.

You do realize that as you are not a customer, anything that you get here is because people that actually want to help contributed time & effort to give you advice, right?

Chris Marisic

unread,
Feb 6, 2013, 8:28:09 AM2/6/13
to rav...@googlegroups.com
James,

It is not our job to solve your software needs. We all provided insight into ways you could solve various modeling concerns, it's up to you to actually evaluate what's appropriate for your business. This is a major difference with RDMBS, you have no decisions in the design process you do it as RDBMS tells you or you will fail. If you want me or one of us to write your application, many would likely be available for consulting. With the treatment you've shown people who attempted to aid you for nothing in return, I would only be willing to offer services to you at a minimum bill rate of $500/hr to tolerate your continued belligerence.
Reply all
Reply to author
Forward
0 new messages