Search code examples
databasemodeluniqueidentifierownership

Is a data model driven resource Id a facet of the resource or of the database?


My examples are going to involve pseudo C# code for discussion purposes, but this is not specific to any single language or database tooling.

Take a simple model

Customer { string Id }

Using RavenDB when I store new Customer() it will generate an id for me at execution time, suppose "Customers/234". In this scenario I'm fine with accepting that id is a facet of RavenDB. Fundamentally this is absolutely no different than Guid.NewGuid().ToString() as it creates an identifier that has no human understandable meaning and merely achieves the goal of global uniqueness (to this database). This is just arguably a nicer version of a guid, and will create better URLs and allow a human to communicate their id if it's ever needed far easier than a string of 16 random hex characters.

In another scenario take:

User { string UserName, string Id }

In this scenario I want to place true semantic meaning into my Id as opposed to just an unique number.

With RavenDB this could be accomplished similar to:

store.Conventions.DocumentKeyGenerator = (entity) => 
{
   User user = entity as User;
   if(user == null)
      return  defaultKeyGeneration (entity);

  return "Users/" + user.UserName;
}

Which then during this store operation you would end up with "Users/dotnetchris"

I could also approach this by instead of having User have a simple property for Id, to use a read-only property:

User {
    string Id { get { return "Users/" + UserName }

I'm having a hard time deciding which of these is the proper place for this construct.

I'm leaning towards it should be included in the class directly, as this gives you information that it will be easy to load this object by id from user input without actually needing to query to the datbase to find Users.Where(user.UserName == "dotnetchris")


Solution

  • As a rule I strive for every single identifier to be owned by the application and not the database. The only reason I will pass ownership of a model's identity is performance reasons, e.g. a SQL table that needs replicated and has 500 million rows.