Auto - ID incrementale nell'oggetto dominio

1

Ho letto molto sull'ID auto-incrementale (guid, interlocked.increment, ObjectIdGenerator ...) ma non trovo nulla per la mia situazione.

Nel mio modello di dominio, l'utente chiede di avere un ID numerico progressivo automatico per ogni attività che creano.

Poiché si tratta di una richiesta utente, desidero inserirla nel mio modello di dominio, ma la modalità che di solito faccio in un'applicazione meno recente senza una buona architettura) è l'accesso al database, il recupero del massimo e l'aggiunta di 1; quindi non posso farlo nel mio oggetto dal momento che il livello di dominio non deve essere a conoscenza di db.

Non mi piace l'identità di db per mancanza di controllo (a volte l'amministratore di db deve modificare l'id per l'errore dell'utente alla creazione di attività).

interlocked.increment ha un bell'aspetto ma la mia applicazione è installata su ogni macchina utente, quindi non posso usarla

Poiché deve essere comprensibile e progressivo, non posso usare guid

Trovo una buona idea nell'articolo di Lev Gorodinski sul Domain di servizio in Domain-Driven-Design: definisci l'interfaccia di un GenerateActivityId nel livello di dominio come un servizio di dominio, ma non trovo un modo per fare una buona implementazione di esso.

Qualche suggerimento?

EDIT: Idea di Lev Gorodinski:

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()
}

ma non vedo dove è definito "generatore" e non ho trovato l'implementazione di IIdGenerator: dove devo inserire l'implementazione? In ActivityRepository? Se sì, posso omettere IIdGenerator per IActiviryRepositoryInteface?

    
posta gt.guybrush 13.09.2013 - 11:00
fonte

3 risposte

0

La mia 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();
}

Livello accesso ai dati

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

Da qualche parte (dove?) definisco l'iniezione di dipendenza con Ninject

var kernel = new StandardKernel();
kernel.Bind<IActivityRepository>().To<ActivityRepository>();
    
risposta data 16.09.2013 - 11:54
fonte
1

Separare l'esigenza dell'utente di un numero di ordine dalla chiave primaria / ID nel database. Assicurati di identificare perché vogliono questo sistema di numerazione e cosa pensano di fare con esso.

Se questo rappresenta l'ordine in cui sono entrati nelle loro Attività, come gestisci una cancellazione? Ti lascia una lacuna nella numerazione? Se l'ordine di ingresso è la forza trainante, salvare la data / l'ora di entrata e quindi è possibile creare un numero d'ordine / ID al volo. Questo può anche essere una parte di un'istruzione select da un database usando un qualche tipo di funzione Row_Number se non vuoi farlo nella tua app. Sono molto efficienti, ma dovresti eseguirlo su tutti i record e poi recuperare un sottoinsieme di quei record. Se le prestazioni diventano un problema, dovrai salvare i valori e poi avere una funzione di riordino dopo una cancellazione.

Se le lacune nel sistema di numerazione sono OK, allora puoi rendere questo numero permanente. Per aggiungere un nuovo numero, è sufficiente interrogare il database e ottenere l'ultimo. Non è diverso dal ritirare qualsiasi altro valore. I DB sono piuttosto efficienti nell'ottenere valori Max ().

EDIT: Non vedo alcun motivo per cui questo non può essere generato nel database. Non deve essere la chiave primaria solo incrementata automaticamente. So che un DBA potrebbe cambiare PK se questa app si sviluppa in un ambiente replicato o qualcuno vuole mettere un po 'di intelligenza nel numero. Gli utenti devono capire cambiando questi numeri corrono il rischio di non poterli fare riferimento allo stesso modo nei loro futuri incontri (supponendo che qualcuno conservi tutte le copie cartacee).

    
risposta data 13.09.2013 - 14:38
fonte
0

È possibile utilizzare un oggetto sequenza e ottenere il valore successivo nel metodo GenerateId. L'uso di una sequenza DB significa che non è necessario utilizzare il massimo dell'identità o l'utilizzo di interlocked.increment che non funzionerà in uno scenario multi-server con bilanciamento del carico. SQL Server 2012 e Oracle support sequences.

    
risposta data 16.09.2013 - 13:44
fonte

Leggi altre domande sui tag