2012-01-23 10 views
8

Inserisco molti dati in SQL Server CE 4.0 utilizzando Entity Framework 4.2 (code-first) e le prestazioni sono pessime rispetto a quelle dirette Inserimento SQL.Prestazioni molto scarse per l'inserimento batch con SQL Server CE 4.0 e Entity Framework 4.2

Il modello è molto semplice:

public class DocMember 
{ 
    public DocMember() { this.Items = new List<DocItem>(); } 

    public int Id { get; set; } 

    public string Name { get; set; } 
    public string MemberType { get; set; } 
    public string AssemblyName { get; set; } 

    public virtual IList<DocItem> Items { get; set; } 
} 

public class DocItem 
{ 
    public int Id { get; set; } 
    public DocMember Member { get; set; } 
    public string PartType { get; set; } 
    public string PartName { get; set; } 
    public string Text { get; set; } 
} 

devo 2.623 DocMembers e un totale di 7747 di DocItems per inserire, e sto ottenendo i seguenti tempi di esecuzione:

With SQL: 00:00:02.8 
With EF: 00:03:02.2 

posso capisco che c'è un po 'di overhead con EF, ma è 65 volte più lento di SQL!

Forse c'è un problema nel mio codice, ma è abbastanza semplice e non riesco a vedere quello che potrebbe essere sbagliato:

private TimeSpan ImportMembersEF(IList<DocMember> members) 
    { 
     using (var db = new DocEntities()) 
     { 
      db.Database.CreateIfNotExists(); 

      var sw = Stopwatch.StartNew(); 
      foreach (var m in members) 
      { 
       db.Members.Add(m); 
      } 

      db.SaveChanges(); 
      sw.Stop(); 
      return sw.Elapsed; 
     } 
    } 

Ho anche provato a chiamare SaveChanges per ogni elemento inserito, oppure ogni 100 o 200 articoli, senza alcun risultato (in realtà lo rende peggiore).

C'è un modo per migliorare le prestazioni o devo usare SQL per gli inserimenti batch?


EDIT: per completezza, ecco il codice per l'inserimento SQL: http://pastebin.com/aeaC1KcB

+0

Sono l'auto 'Id's generato sul server? – Eranga

+0

Non ho idea se questo abbia qualcosa a che fare con la prestazione lenta, ma mi chiedo se, secondo la convenzione, 'DocMemeber Member pubblico {get; impostato; } 'dovrebbe essere' public DocMember DocMember {get; impostato; } 'e anche se ci dovrebbe essere un membro' public int DocMember DocMemberId {get; impostato; } '. – devuxer

+0

@Eranga, si. Non ho specificato nulla al riguardo, è il comportamento predefinito. –

risposta

6

È possibile utilizzare la mia libreria SqlCeBulkCopy per il caricamento dei dati di massa, che imita l'API SqlBulkCopy: http://sqlcebulkcopy.codeplex.com

+0

Grazie, ma non risponde alla mia domanda ... Non ho problemi di prestazioni se lo faccio in SQL (anche se probabilmente potrebbe essere migliorato usando copia bulk), il mio problema è con Entity Framework –

+0

In realtà ho appena notato qualcosa di interessante: "il metodo WriteToServer accetta anche un DataTable, un IEnumerable o e ** IEnumerable **". Accetta POCO o deve essere entità generate da EF? –

+0

No, può essere qualsiasi elenco di oggetti, ad esempio POCO – ErikEJ

1

E 'lento perché non è il dosaggio dell'inserto.

Quando si inserisce l'identità sul db, è necessario selezionare l'ID risultato dopo ogni elemento da assegnare al modello. Questo lo rende veramente lento.

L'SQL ad hoc non sta selezionando l'ID in modo che, in batch, è possibile inviare tutte le dichiarazioni contemporaneamente.

Altho scritto con NHibernate:

http://www.philliphaydon.com/2011/09/the-benefits-of-letting-the-orm-generate-the-identity-part-1/

ho scritto sull'utilizzo ORM generato ID vs ID SQL generato.

+0

Il mio SQL ad hoc non sta facendo il batch degli inserimenti e recupera l'ID ... aggiornerò la domanda. –

+0

Seleziona l'ID dopo ogni inserimento e lo assegna al modello? – Phill

+0

si, vedere il link alla fine della mia domanda –

Problemi correlati