2009-04-15 15 views
7

Ho un database che fa parte di uno schema di replica di merge che ha un GUID in quanto è PK. In particolare, il tipo di dati è uniqueidentifier, valore predefinito (newsequentialid()), RowGUID è impostato su . Quando faccio un InsertOnSubmit (CaseNote) pensavo di poter lasciare CaseNoteID da solo e il database avrebbe inserito il successivo GUID sequenziale come fa se immetti manualmente una nuova riga in MSSMS. Invece invia 00000000-0000-0000-0000-000000000000. Se aggiungo CaseNoteID = Guid.NewGuid(),, ottengo un GUID ma non sequenziale (ne sono abbastanza sicuro).LINQ to SQL Inserisci GUID sequenziale

C'è un modo per consentire a SQL di creare il successivo ID sequenziale su LINQ InsertOnSubmit()?

Per riferimento è il codice che sto usando per inserire un nuovo record nel database.

  CaseNote caseNote = new CaseNote 
           { 
            CaseNoteID = Guid.NewGuid(), 
            TimeSpentUnits = Convert.ToDecimal(tbxTimeSpentUnits.Text), 
            IsCaseLog = chkIsCaseLog.Checked, 
            ContactDate = Convert.ToDateTime(datContactDate.Text), 
            ContactDetails = memContactDetails.Text 
           }; 
     caseNotesDB.CaseNotes.InsertOnSubmit(caseNote); 

     caseNotesDB.SubmitChanges(); 

Sulla base di uno dei suggerimenti di seguito ho attivato l'Autogenerated in LINQ per quella colonna e ora ottengo il seguente errore ->La tabella di destinazione dell'istruzione DML non può avere alcun trigger attivata se la dichiarazione contiene una clausola OUTPUT senza clausola INTO. Idee?

risposta

5

Nella finestra di progettazione da Linq a Sql, impostare la proprietà Valore generato automaticamente su true per quella colonna.

Questo è equivalente a IsDbGenerated property per una colonna. L'unica limitazione è che non è possibile aggiornare il valore utilizzando Linq.

+0

Ho provato questo e ho ora ottenere il seguente errore -> La tabella di destinazione dell'istruzione DML non può avere alcun trigger attivati ​​se l'istruzione contiene una clausola OUTPUT senza clausola INTO. –

+0

perché hai accettato la risposta se non funziona? – guiomie

+0

Per me questo era già impostato, ma il DB tenta ancora di assegnare il valore predefinito di 0 anziché guidarne uno. – DCShannon

5

Dalla parte superiore della scatola "correlate" a destra:

Sequential GUID in Linq-to-Sql?

Se si vuole veramente il valore di "prossimo", utilizzare un Int64 invece di GUID. Il comando COMB assicurerà che i GUID siano ordinati.

+2

+1. Se vuoi ordinare, usa un tipo numerico. I Guids sono stati progettati per funzionare come identificatori univoci, non forniscono alcun metodo di ordinazione. –

+0

true, ma può causare molto churn in due casi: indicizzazione cluster e prestazioni di replica (che assomiglia al problema dell'OP).La COMB aiuta con quello, ma non li rende necessariamente sequenziali. –

+0

@ Michael - grazie per averlo indicato. È strano che non fosse uno dei "suggerimenti" quando ho creato il titolo –

1

Per quanto riguarda il tuo "La tabella di destinazione dell'istruzione DML non può avere trigger attivati ​​se l'istruzione contiene una clausola OUTPUT senza clausola INTO", leggi questo articolo MS KB, sembra un bug in LINQ:

http://support.microsoft.com/kb/961073

1

Hai davvero bisogno di fare un paio di cose.

  1. Rimuovere qualsiasi incarico alla proprietà tipo GUID
  2. Modificare la colonna generata automaticamente
  3. Creare un vincolo nel database di default nella colonna a NEWSEQUENTIALID()
  4. Do inserire sulla presentare proprio come eri prima.

Sull'inserto nella tabella l'ID verrà creato e sarà sequenziale. Performance comparison of NEWSEQUENTIALID() vs. other methods

+0

@C Tierney: come si differenzia dalla soluzione accettata? Sembra la stessa cosa, spiegata, corretta? –

0

Masstransit utilizza un combguid:

https://github.com/MassTransit/MassTransit/blob/master/src/MassTransit/NewId/NewId.cs

è questo quello che stai cercando?

da wikipedia:

algoritmi sequenziali

GUID sono comunemente utilizzati come chiave primaria di tabelle del database, e con questo, spesso la tabella ha un indice cluster quell'attributo. Questo presenta un problema di prestazioni quando si inseriscono record poiché un GUID completamente casuale a significa che il record potrebbe dover essere inserito ovunque nella tabella anziché semplicemente aggiunto alla fine di esso. Come un modo di mitigare questo problema pur fornendo ancora abbastanza casualità per prevenire efficacemente la duplicazione dei numeri duplicati, diversi algoritmi sono stati utilizzati per generare GUID sequenziali. La prima tecnica, descritta da Jimmy Nilsson nell'agosto 2002 [7] e denominata "COMB" ("combinata guid/timestamp"), sostituisce gli ultimi 6 byte di Data4 con i meno significativi 6 byte del data/ora del sistema corrente. Anche se questo può causare GUID generati fuori ordine all'interno di nella stessa frazione di secondo, i suoi test hanno mostrato che questo ha avuto un impatto reale sull'inserimento di nel mondo reale. Un effetto collaterale di questo approccio è che la data e l'ora dell'inserimento possono essere facilmente estratti dal valore in seguito, se lo si desidera. A partire da Microsoft SQL Server versione 2005, Microsoft ha aggiunto una funzione al linguaggio Transact-SQL denominato NEWSEQUENTIALID(), [8] che genera GUID garantiti per l'incremento di , ma può iniziare con un numero inferiore (comunque garantito univoco) al riavvio del server. Ciò riduce il numero di pagine di tabella in cui possono verificarsi inserimenti, ma non garantisce che i valori di aumentino sempre di valore. I valori restituiti da questa funzione possono essere facilmente previsti, quindi questo algoritmo non è adatto allo per generare numeri oscuri a scopo di sicurezza o di hashing. In 2006, un programmatore ha rilevato che la funzione SYS_GUID fornita da Oracle restituiva GUID sequenziali su alcune piattaforme, ma questo sembra essere un errore piuttosto che una funzionalità [9].

0

È necessario gestire il metodo OnCreated()

Partial Class CaseNote 
    Sub OnCreated() 
     id = Guid.NewGuid() 
    End Sub 
End Class