id, ID, Id, ItemId, or...?
I've been working with Azure DocumentDB recently, and my primary goal in using it was migrating an existing data model and schema into it. The primary problem I ran in to is that DocumentDb requires a serialized JSON property of id, yes, lowercase. This goes against typical C# naming conventions where you'd typically see a property of Id, or ID, and maybe even ItemId. Because a Document is nothing but JSON, this probably is easily solved by applying a JSON.NET attribute to force ID to serialize out as id,like so: But since I'm not interested (or maybe you can't) in modifying my existing data model, this isn't enough.
// (Optional) Disables the automatic id generation, If this is True the system will throw an exception if the id property is missing from the Document.
AutomaticIdGeneration is a feature within the .NET Client SDK that will automatically generate an id (again, lowercase) for you if a property doesn't exist by that name. The reason I don't find this helpfulis because I want and need to track my Id property throughout my application. We could just let DocumentDB automatically create the ID property, and my application only query for documents that contain my Id. This is fine and all, until you have a bug in the application, and end up with two doucments that have the same Id (from your application). We can see the experience of AutomaticIdGeneration when exploring the Document Browser from the Azure Preview Portal.
When clicking New Document , the JSON editor defaults an id property for you.
What happens when we try changing id to ID?
Then hit save. Our ID property stayed the same as the editor showed, but DocumentDB automatically created an id property for us. This is the default behavior of the .NET SDK by way of the disableAutomaticIdGeneration property (defaulted to false).
Then if we try deleting id, we get an error. This is the behavior of the .NET SDK by setting the disableAutomaticIdGeneration property to true.
With the above said, I decided to come up with my own solution that allows me to use any existing C# class, and not make any modifications to them. I still get to know what my ID is throughout the application. We'll start by enheriting from the Documentclass. By doing so, we'll automatically get properties such as ETag, Timestamp (modified), etc that document has out of the box (thanks Ryan in the comments! Make sure you go read his response below). I'm also adding a Type string (because I am sharing multiple data types in a single collection) to make querying more simple, and a T Document. T Document is going to be the object type we actually want to put into DocumentDB. Note:You must add the redundant JsonProperty onto the Type & Document properties. The Document base class doesn't serialize the properties without.
I created myself two extension methods to make use of this new wrapper class, Wrap and Unwrap. Wrap is an extension method to the objectclass, then takes a Functhat is used to determine what property on the object should be used for the Id. It also sets our timestamp & the Type. We then use this method like so. The object passed to the SDK is myobjectInstance wrapped as DocumentWrap, and we define a Func that says, select the ID property as our id. Then when you want to query for this object to get out of DocumentDB, you create your query using the DocumentWrap type to be used to deserialize the JSON. Lastly, the Unwrapmethod will just get our instance of MyEntityback out. Finally, here's what our document looks like inside of DocumentDB (with some of the closing JSON omitted).
Update: Amends to the original post made based on feedback from Ryan CrawCour below. Thanks Ryan! Have fun Azure'ing!