0

i have this problem modelling one of my entities:

  1. My entity must have a mandatory ID field that user use to recognize single object
  2. User don't want to manual enter ID but it must be generate by Application incrementing by 1 every time
  3. Appllication resides only on clients machine, on server there is only the db

According to 1. I create Id field as mandatory (and not nullable), in this way it must be provided to create an instance but how can program know which ID has to use?

Ideally i have to query db to get max id, add 1 and use this value but how can do it? To mee it seem a matter of my domain object, and i want to isolate domain layer from data access layer so i cant call directly repository from by entity.

Possible solutions:

  1. I look to Interlocked.Increment but how can use it if any user can create a new instance on his client?
  2. Move the logic to Application Logic layer: there i can call the repository, get the ID, create the class and call repository to save class. in this way a move a domain logic (the incremental id is a specific user request) out of domain layer
  3. Define repository interface in Domain Layer, call the interface in constructor method of my entity. All doing with dependecy injection, but how? I use ninject in my bootstrapper and all references goes from top to down, how can i revert it for domain layer making it call a superior layer avoiding service locator antipattern (otherwise a can simply write NinjectKernel.Get() in my ctor)
  4. i found this article and it's interesting but he use my solution in a bad way (without interface) and don't define the field as mandatory so he can create a new instance withoud specify id

Are there a better solutions?

EDIT

some code to better explain tha case:

Public MyClass {
 public int Id{get;set;}
 .....

 public MyClass(int id){
  if(id != null)
   this.Id = id;
  else
   throw (new ArgumentException)

  .....
 }
}

So i cant do MyClass mc = new MyClass(null); but i need to have the id before

in Data Access Layer i use NHibernate and have Uow / Repository pattern

after i can get a valid ID a can write

UnitOfWork.MyClassRepository.Add(mc);
Community
  • 1
  • 1
gt.guybrush
  • 1,320
  • 3
  • 19
  • 48
  • Will the entity not exist in the DB? What is preventing you from just using identity/autoincrement/whatever your DB specifies for a unique ID it automatically assigns? – John Straka Jun 06 '14 at 12:17
  • Have you think about GUID? – MikkaRin Jun 06 '14 at 12:22
  • but the db identity is generate only when i write object to db, so first i have to create an object and cant to it without having the ID – gt.guybrush Jun 06 '14 at 12:40
  • the id have to be used by user in official document so must be readable, GUID is too complex – gt.guybrush Jun 06 '14 at 12:41
  • Why couldn't you write it to the DB when the user initiates creation? Is there any reason you don't want it to persist? – John Straka Jun 06 '14 at 12:47
  • i cant create a new instance if the id is not specified (since i want to have it mandatory), so i have nothig to persist – gt.guybrush Jun 06 '14 at 13:04
  • If it's an identity column it can't be manually populated and would automatically be determined when the record is inserted. What are you using for DB access? – John Straka Jun 06 '14 at 13:07
  • Is Id not the primary key? I haven't used NHibernate but no ORM should require that to be populated before creation... – John Straka Jun 06 '14 at 13:19

2 Answers2

0

There's another solution, used by some high load distributed apps. The idea is to create a separate service (web service) to get you a new ID. Inside, implementation could be as simple as:

public int GetNextId()
{
    return Interlocked.Increment(ref _lastId);
}

Although you obviously have to fetch last id from database at service start.

Then, you just make each of your client apps to call this service before creating an entity.

But honestly I'd start with database generated Id or using Guids if possible.

UPDATE: Another option. Assign a unique id (int) to each client. Then use internal counter each time you need a new Id, but mix it with client as as ClientId * 10000 + LastId. This is similar to Hi/Lo generator.

Kostassoid
  • 1,870
  • 2
  • 20
  • 29
  • i don't have an applications server which can run this service, all code must reside in app distribuited on client machine. for other way see my comment above – gt.guybrush Jun 06 '14 at 12:43
  • very interesting, but user want a progressive counter among all users, without so many spaces. Meantime i will look deeper in Hi/lo generator – gt.guybrush Jun 06 '14 at 13:07
0

In your domain model you can create repository which takes id from DB. And you must create factory of your domain objects which uses repository for generating id.

IL_Agent
  • 707
  • 3
  • 16