1

I read a lot about auto-incremental id (guid, interlocked.increment, ObjectIdGenerator...) but don't find nothing for my situation.

In my domain model user ask to have an automatic progressive numeric Id for each Activity they create.

Since it's a user request I want to put it in my domain model, but the mode I usually do it in older application without good architecture ) is accessing database, retrieve the max and add 1; so I can't do it in my object since domain layer must not be aware of db.

Don't like db identity for lack of control (sometimes db administrator have to change the id for user error on creation of activity).

interlocked.increment look fine but my application is installed on every user machine so I can't use it

Since it must be intelligible and progressive I can't use guid

I find a good idea in Lev Gorodinski article about Service Domain in Domain-Driven-Design: define the interface of a GenerateActivityId in domain layer as a Domain Service, but I don't find a way to make a good implementation of it.

Any suggestion?

EDIT: Lev Gorodinski idea:

public class Activity {
  public int Id {get; private set;}
  public string Description {get;set;}

  public Activity (string description){
    this.Description = description 
    this.Id = generator.GenerateId()
  }
}

public interface IIdGenerator{
  int GenerateId()
}

but i don't see where "generator" is defined and don't found IIdGenerator implementation: where should i put the implementation? In ActivityRepository? If yes i can omit IIdGenerator for the IActiviryRepositoryInteface ?

1

Separate the user's need for some order number from the Primary Key/ID in the database. Make sure you identify why they want this numbering system and what they plan on doing with it.

If this represents the order they've entered their Activities, how do you handle a deletion? Do you leave a gap in the numbering? If order of entry is the driving force, save the date/time of entry and then you can create an order number / ID on the fly. This can even be a part of a select statement from a database using some type of Row_Number function if you don't want to do it in your app. They're very efficient, but you would have to perform this on all the records and then retrieve a subset of those records. If performance becomes a problem, you're going to have to save the values and then have some a ReOrdering function after a deletion.

If gaps in the numbering system are OK, then you can make this number permanant. To add a new number, you just need to query the database and get the last one. It's no different than retreiving any other value. DBs are pretty efficient at getting Max() values.

EDIT: I don't see any reason why this can't be generated in the database. It doesn't have to be the primary key just auto incremented. I know a DBA might change PK's if this app grows into some replicated environment or someone wants to put some intelligence in the number. The users need to understand by changing these numbers they run the risk of not being able to reference them the same way in their future meetings (Assuming someone keeps all the paper copies.).

  • they need a code for each activity to use it in meetings and simply identify it over time. Gap is allowed and entry order is not driving because there is status too for know start date, so smaller code can have greater status start date. practically it's only an user frienly identifier. My problem now is where to put id creation in code: i have factory for creating object that don't ask the id because it's his job creating it but how? calling repository where a method query the database for get maxId? – gt.guybrush Sep 13 '13 at 13:39
  • I edited question with Gorodinski idea and my doubt about it – gt.guybrush Sep 13 '13 at 13:51
  • 1
    You're going to a lot of trouble to reinvent the wheel. Don't think too far ahead. – JeffO Sep 13 '13 at 14:02
  • ok that's diffcult but how to make constructor work with domain model not aware of data access implementation (like good layer architecture or onion architecture? – gt.guybrush Sep 13 '13 at 14:12
  • if its generated in db how can my object Activity work? it's non complete till i call repository for accessing db, so where have i to put the logic? in business layer? and the predicate to keep domain logic in domain object? – gt.guybrush Sep 14 '13 at 7:15
0

My idea:

Domain Layer

public class Activity {
  public int Id {get; private set;}
  public string Description {get;set;}

  public Activity (string description){
    this.Description = description 
    var activityRepository = kernel.Get<IActivityRepository>();
    this.Id = activityRepository .GetMaxId() + 1 
  }
}

public interface IActivityRepository{
  public int GetMaxId();
}

Data Access layer

public class ActivityRepository
{
    pulic int GetMaxId()
    {
      // query for retriving max id from table
    }
}

Somewhere (where?) i define dependecy injection with Ninject

var kernel = new StandardKernel();
kernel.Bind<IActivityRepository>().To<ActivityRepository>();
0

You can use a sequence object and get the next value in your GenerateId method. Using a DB sequence means you don't have to use the Max of identity or using interlocked.increment which will not work in a load balanced multi-server scenario. SQL Server 2012 and Oracle support sequences.

  • it's a good thing but iam forced with sql 2008, but will keep in mind for future evolution (not enough reputation for giving +1) – gt.guybrush Sep 16 '13 at 12:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.