Domanda

Sto progettando un sistema abbastanza complesso. Una delle nostre preoccupazioni principali è il supporto della replica peer-to-peer di SQL Server. L'idea è di supportare diversi nodi separati geograficamente.

Una preoccupazione secondaria è stata l'utilizzo di un ORM moderno nel livello intermedio. La nostra prima scelta è sempre stata Entity Framework, principalmente perché agli sviluppatori piace lavorare con esso. (Adorano il supporto LiNQ.)

Quindi, ecco il problema:

Con in mente la replica peer-to-peer, ho deciso di utilizzare uniqueidentifier con un valore predefinito di newsequentialid () per la chiave primaria di ogni tabella. Ciò sembrava fornire un buon equilibrio tra evitare collisioni chiave e ridurre la frammentazione dell'indice.

Tuttavia, si scopre che la versione corrente di Entity Framework ha un limitazione molto strana : se la colonna chiave di un'entità è un identificatore univoco (GUID), non può essere configurato per utilizzare il valore predefinito (newsequentialid ()) fornito dal database. Il livello dell'applicazione deve generare il GUID e popolare il valore chiave.

Quindi, ecco il dibattito:

  1. abbandonare Entity Framework e utilizzare un altro ORM:
    • usa NHibernate e rinuncia al supporto LiNQ
    • usa linq2sql e rinuncia al supporto futuro (per non parlare di essere legato a SQL Server su DB)
  2. abbandona i GUID e scegli un'altra strategia PK
  3. escogita un metodo per generare GUID sequenziali (COMB?) a livello dell'applicazione

Mi sto avvicinando all'opzione 1 con linq2sql (ai miei sviluppatori piace molto linq2 [roba]) e 3. Questo è principalmente perché sono un po 'ignaro delle strategie chiave alternative che supportano lo schema di replica a cui puntiamo, pur mantenendo cose sane dalla prospettiva di uno sviluppatore.

Qualsiasi approfondimento o opinione sarebbe molto apprezzato.

È stato utile?

Soluzione

Un'altra opzione (non disponibile al momento della pubblicazione) è l'aggiornamento a EF 4, che supporta GUID generati dal server.

Altri suggerimenti

Secondo suggerimento di Craig - opzione 4.

Puoi sempre usare la colonna GUID, popolata dal livello intermedio, come PRIMARY KEY (che è un costrutto LOGICAL).

Per evitare una frammentazione massiccia dell'indice (quindi: tabella), usa qualche altra chiave (idealmente una colonna INT IDENTITY) come CHUSTER CHIAVE - che è un costrutto di database fisico, che PUO 'essere separato dalla chiave primaria.

Per impostazione predefinita, la chiave primaria è la chiave di clustering, ma non deve essere così. In effetti, ho migliorato le prestazioni e ridotto drasticamente la frammentazione facendo proprio questo su un database che "ereditato". - aggiungi una colonna INT IDENTITY e metti la chiave di clustering su quel piccolo, sempre crescente, mai mutevole INT - funziona come un incantesimo!

Marc

Eh? Penso che le tue tre opzioni siano una scelta falsa. Prendi in considerazione l'opzione 4:

  

4) Utilizzare Entity Framework con non sequenziali , GUID generati dal client.

L'EF non può vedere i GUID generati dal server DB per le nuove righe inserite dal framework stesso , certo, ma non è necessario generare i GUID sul server DB. È possibile generarli sul client quando si creano le istanze dell'entità. L'intero punto di un GUID è che non importa dove lo generi. Per quanto riguarda i GUID generati da un DB replicato, l'EF li vedrà bene.

I tuoi GUID lato client non saranno sequenziali (usa Guid.NewGuid ()), ma saranno in tutto il mondo, garantiti unici.

Lo facciamo nella spedizione, software di produzione con replica. funziona .

Perché non utilizzare la colonna identità? Se si esegue la replica di tipo merge, è possibile avviare ciascun sistema da un seed separato e lavorare in una direzione (ad esempio il nodo a inizia da 1 e aggiunge 1, il nodo b inizia da 0 e sottrae uno) ...

È possibile utilizzare le procedure memorizzate se si è realmente bloccati sull'uso di NewSequentialID (). È possibile associare le colonne dei risultati dalla procedura alla proprietà appropriata e una volta inserito il GUID generato da SQL verrà reinserito nell'oggetto.

Sfortunatamente devi definire SP per tutte e tre le operazioni (inserire, aggiornare, cancellare) anche se le altre operazioni si completerebbero correttamente usando i valori predefiniti. È inoltre necessario mantenere il codice SP e assicurarsi che sia sincronizzato con il modello EF mentre si apportano modifiche, il che potrebbe rendere questa opzione poco attraente a causa del sovraccarico aggiuntivo.

C'è un esempio passo-passo in http://blogs.msdn.com/bags/archive/2009/03/12/entity-framework-modeling-action-stored-procedures.aspx che è piuttosto semplice -Forward.

usa newseqid con il tuo orm (non è così difficile) con linq

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top