2012-01-23 12 views
8

Estoy insertando una gran cantidad de datos en SQL Server CE 4.0 utilizando Entity Framework 4.2 (código primero), y el rendimiento es abismal cuando se compara con direct Inserción SQLRendimiento muy bajo para inserción por lotes con SQL Server CE 4.0 y Entity Framework 4.2

El modelo es muy simple:

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; } 
} 

que tienen DocMembers 2623 y un total de 7747 de DocItems para insertar, y me estoy poniendo los siguientes tiempos de ejecución:

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

que pueda entiendo que hay un poco de sobrecarga con EF, pero es 65 veces ¡más lento que SQL!

Tal vez hay un problema en mi código, pero es bastante sencillo y no puedo ver lo que podría estar equivocado:

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; 
     } 
    } 

también tratamos de llamar SaveChanges para cada elemento insertado, o cada 100 o 200 artículos, en vano (en realidad lo empeora).

¿Hay alguna manera de mejorar el rendimiento o tengo que usar SQL para inserciones por lotes?


EDIT: esté completo, aquí está el código para la inserción de SQL: http://pastebin.com/aeaC1KcB

+0

son el 'automático Id's generados en el servidor? – Eranga

+0

No tengo idea si esto tiene algo que ver con el bajo rendimiento, pero me pregunto si, según la convención, 'miembro público de DocMemeber {get; conjunto; } 'debe ser' público virtual DocMember DocMember {get; conjunto; } 'y también si debe haber un miembro' público int DocMember DocMemberId {get; conjunto; } ' – devuxer

+0

@Eranga, sí. No especifiqué nada sobre esto, es el comportamiento predeterminado. –

Respuesta

6

Puede usar mi biblioteca SqlCeBulkCopy para los datos de carga a granel, que imita la API SqlBulkCopy: http://sqlcebulkcopy.codeplex.com

+0

Gracias, pero no responde mi pregunta ... No tengo problemas de rendimiento si lo hago en SQL (aunque probablemente podría mejorarse mediante el uso de copia masiva), mi problema es con Entity Framework –

+0

En realidad acabo de notar algo interesante: "el método WriteToServer también acepta un DataTable, un IEnumerable oy ** IEnumerable **". ¿Acepta POCOs, o tiene que ser entidades generadas por EF? –

+0

No, puede ser cualquier lista de objetos, es decir, POCOs – ErikEJ

1

Es lento porque no está entre lotes La inserción.

Al insertar el uso de la identidad en la base de datos, tiene que seleccionar la ID del resultado después de cada elemento para asignar al modelo. Esto lo hace realmente lento.

Su adhoc SQL no está seleccionando la identificación, por lo que cuando se procesa por lotes puede enviar todas las declaraciones a la vez.

Altho escrito con NHibernate:

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

me escribió acerca del uso de ORM genera identificadores vs identificadores SQL generado.

+0

Mi adhoc SQL tampoco carga las inserciones, y recupera la identificación ... Actualizaré la pregunta. –

+0

¿Está seleccionando la ID después de cada inserción y asignándola al modelo? – Phill

+0

sí, consulte el enlace al final de mi pregunta –

Cuestiones relacionadas