2012-06-05 14 views
5

Sto usando gli attuali tick dell'orologio come seme per la generazione di numeri casuali. Il numero casuale viene utilizzato in uno pseudo GUID e un controllo nel mio database assicurerà che non esista già prima di tornare. In media, questo metodo verrà chiamato circa 10k volte in successione durante la vita del processo.Utilizzare il quadrante dell'orologio come seme casuale numero

La mia preoccupazione è che un numero identico possa essere generato da un back to back con conseguente più chiamate ricorsive non necessarie al mio database che controlla lo stesso ID. Mi piacerebbe evitare questo, se possibile. Qual è il modo migliore per testare questo scenario?

Se è importante, l'applicazione è NET 4 e il database è SQL Server 2008.

private static string GenerateUniqueDelId() 
{ 
    // Generate a random integer using the current number of clock ticks as seed. 
    // Then prefix number with "DEL" and date, finally padding random integer with leading zeros for a fixed 25-character total length. 
    int seed = (int)DateTime.Now.Ticks; 
    Random number = new Random(seed); 
    string id = string.Format("DEL{0}{1}", DateTime.Today.ToString("yyyyMMdd"), number.Next().ToString("D14")); 

    // Lookup record with generated ID in Sesame. If one exists, call method recursively. 
    string query = "SELECT * FROM Lead WHERE Esm_Id = @Esm_Id"; 
    SqlParameter[] parameters = { new SqlParameter("@Esm_Id", id) }; 
    if (DataManager.GetRow(query, parameters, DelConnection.Sesame) != null) return GenerateUniqueDelId(); 

    // Otherwise, return ID. 
    return id; 
} //// End GenerateUniqueDelId() 
+3

Se avete intenzione di SQL Server per verificare la presenza di loro exitance -Perché gergo li generi li al primo posto? – YavgenyP

+0

In alternativa all'utilizzo di un numero casuale, puoi invece utilizzare una colonna 'Identity'? – Matthew

+2

Perché non usare solo un GUID. Non sono un grande fan di ricreare una ruota. –

risposta

10

Hai ragione nella vostra preoccupazione: è necessario spostare la creazione del vostro Random esempio dal vostro corpo del metodo - altrimenti si ri-seed con lo stesso valore molte volte che si traduce nella stessa sequenza numerica.

Anche tu stai un po 'reinventando la ruota: il costruttore predefinito della classe Random utilizza già l'ora corrente come seme predefinito.

La domanda è: perché non si evita tutto questo e basta utilizzare un Guid generato automaticamente sul lato del database?

+0

L'ID viene utilizzato nel sistema di un fornitore esterno e ha criteri di formattazione specifici: 25 caratteri di lunghezza, prefissati con 3 caratteri alfabetici e data nel formato aaaaMMgg. Posso giocare solo con i rimanenti 14 personaggi. – Brian

+1

Oh e per quanto riguarda il costruttore Random predefinito, grazie per le informazioni. Non sapevo che utilizza i segni di spunta dell'orologio per impostazione predefinita - Sarò sicuro di aggiornarlo nel mio codice! – Brian

+1

Alla fine ho spostato 'Random' al di fuori del mio ciclo, quindi posso passarlo in' GenerateUniqueDelId (Generatore casuale) '. – Brian

6

Citando Jon Skeet

Quando si vede la parola "casuale" in un titolo di domanda su Stack Overflow si può quasi garantire che sarà lo stesso problema fondamentale come innumerevoli domande simili. Questo articolo spiega perché la casualità causa così tanti problemi e come affrontarli.

controllare il suo articolo su generatori di numeri casuali

http://csharpindepth.com/Articles/Chapter12/Random.aspx

fondamentalmente la sua soluzione si presenta come:

using System; 
using System.Threading; 

public static class RandomProvider 
{  
    private static int seed = Environment.TickCount; 

    private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() => 
     new Random(Interlocked.Increment(ref seed)) 
    ); 

    public static Random GetThreadRandom() 
    { 
     return randomWrapper.Value; 
    } 
} 
+0

Grazie, leggerò sicuramente questo articolo. – Brian

+0

Ho ancora ricevuto duplicati usando Environment.TickCount come seme. Ho finito per utilizzare (int) DateTime.UtcNow.Ticks e non ho ancora ricevuto risultati duplicati. –

+0

@JoshDeLong - Questa è la cosa divertente della casualità; Non promette di consegnare mai duplicati :) –

Problemi correlati