Domanda

Ho Progetto C # che utilizza SQL Server Compact Edition e Entity Framework per l'accesso ai dati. Ho la necessità di inserire o aggiornare una grande quantità di righe, 5000+ o più al db, quindi se la chiave esiste aggiornamento il record se non inserisco. Non riesco a trovare un modo per farlo con l'edizione compatta e EF con prestazioni orribili out, vale a dire l'assunzione di 2 minuti, più su un computer core i7. Ho provato a cercare per il record per vedere se esiste quindi inserendo, se non o l'aggiornamento se lo fa, la ricerca è il killer su questo. Ho provato la compilazione della query di ricerca e che ha dato solo un piccolo miglioramento. Un'altra cosa Ive ha provato sta inserendo il record in un tentativo di cattura e se non riesce aggiornamento, ma che mi costringe a SaveChanges su ogni record per ottenere l'eccezione in contrasto con alla fine, che è un killer di prestazioni. Ovviamente non posso utilizzare le stored procedure dal momento che è un'edizione compatta. Inoltre Ho guardato solo l'esecuzione di T-SQL direttamente in qualche modo sul db, ma la mancanza di dichiarazioni di processo compatto sembra escludere questa possibilità. Ho cercato di tutto il mondo e di idee. Volevo usare compatto se posso esprimere nel corso per i benefici di implementazione e la capacità di impedire all'utente di scavare intorno al db. Eventuali suggesitons sarebbe apprezzato.

Grazie

È stato utile?

Soluzione

Forse si potrebbe ottenere il risultato che cercate utilizzando query semplici. Diciamo che la tabella che si desidera inserire nel o l'aggiornamento è come questo

TABLE original
     id integer,
     value char(100)

prima si potrebbe creare una tabella temporanea con i nuovi valori (è possibile utilizzare un SELECT INTO o altri modi per crearla)

TABLE temp
    id integer,
    value char(100)

Ora, è necessario fare due cose, aggiornare le righe in originale e quindi inserire i nuovi valori

UPDATE original 
SET original.value = temp.value
FROM original, temp
WHERE original.id = temp.id

INSERT INTO original 
SELECT * from temp 
WHERE temp.id not IN (select o.id from original o)

Altri suggerimenti

Quando stiamo utilizzando SQL CE (e SQL 2005 Express è per questo) abbiamo sempre chiamare un aggiornamento prima e poi chiamare un inserto se l'udate dà un numero di righe di 0. Questo è molto semplice da implementare e non richiede expensice blocchi try..catch per il flusso di controllo.

Data la dichiarazione del problema, ho intenzione di indovinare che questo software presuppone un ambiente relativamente robusto. Avete pensato di prendere il compito di determinare off di sqlce e di fare da soli? In sostanza, afferrare un elenco ordinato di tutti gli ID (chiavi?) Dalla relativa tabella e controllando ogni chiave oggetto contro tale elenco prima di fare la coda per l'inserimento?

In questo modo alcune assunzioni che sarebbe una cattiva notizia con un tipico DB, ma che probabilmente si può ottenere via con in sqlce. Per esempio, si presuppone che le righe non saranno inseriti o modificati da un altro utente, mentre si sta eseguendo questo inserto in modo significativo.

Se l'elenco delle chiavi è troppo lungo per tenere ragionevolmente in memoria per tale controllo, ho paura direi che sqlce solo potrebbe non essere lo strumento giusto per il lavoro. : (

Non sono sicuro se questo è fattibile o no, come non ho usato Entity Framework, ma hai provato a fare funzionare l'aggiornamento prima e controllando il conteggio delle righe - l'inserimento se nessuna riga è stata aggiornata? Questo può essere più veloce di eccezioni cattura. E 'generalmente una cattiva pratica di utilizzare le eccezioni per il flusso di controllo, e spesso rallenta le cose in modo drammatico.

Se è possibile scrivere direttamente il codice SQL, quindi il modo più veloce per farlo sarebbe quello di ottenere tutti i dati in una tabella temporanea e quindi aggiornare l'esistente e inserire le pause (come nell'esempio di Andrea Bertani sopra). Si dovrebbe ottenere risultati leggermente migliori utilizzando una sinistra unirsi alla tabella originale nel selezionare nel vostro inserto, ed escludendo tutte le righe con i valori della tabella originale che non sono nulli:

INSERT INTO original
SELECT * FROM temp
LEFT JOIN original ON original.id = temp.id
WHERE original.id IS NULL

Ti consiglio di utilizzare direttamente SqlCeResultSet. Si perde il bel tipo-sicurezza di EF, ma le prestazioni sono incredibilmente veloce. Siamo passati da ADO.NET 2.0 TypeDataSets stile a SqlCeResultSet e SqlCeDataReader e visto da 20 a 50 volte gli aumenti in termini di velocità.

Vedere SqlCeResultSet. Per un progetto .NetCF ho rimosso quasi tutto il codice SQL in favore di questa classe. Basta cercare "SqlCeResultSet" qui e MSDN.

Una rapida panoramica:

  1. Aprire il resultSet. Se avete bisogno di chiedere (per il check esistenza) si dovrà fornire un indice per il set di risultati.

  2. Seek sul set di risultati e di leggere per verificare se hai trovato la riga. Ciò è estremamente veloce anche su tabelle con decine di migliaia le righe (perché il chiedere utilizza l'indice).

  3. Inserire o aggiornare il record (vedi SqlCeResultSet.NewRecord).


Abbiamo sviluppato con successo un progetto con un database sqlce con un tavolo prodotto principale con oltre 65000 file (lettura / scrittura con 4 indici).

edizione di SQL Server Compact è abbastanza presto nello sviluppo, a questo punto. Inoltre, a seconda del dispositivo, accesso alla memoria rigido può essere piuttosto lento, e l'overhead SQLCE più NET tipo di sicurezza è piuttosto intenso. Funziona meglio con un archivio di dati piuttosto statici.

Vi suggerisco di usare sia un API più leggero o prendere in considerazione SQLite.

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