2016-07-07 1 views
4

J'ai une solution Web Forms EF6/ASP.NET 4.5 en cours d'exécution, et maintenant je dois ajouter quelques fonctionnalités pour permettre des insertions en vrac à partir de fichiers Excel. Je suis conscient que EF out of the box n'est pas optimisé pour les opérations en vrac, donc j'ai regardé autour et trouvé "EF BulkInsert" (https://efbulkinsert.codeplex.com/) pour faciliter cela.EF.BulkInsert et Glimpse - ne pas bien jouer ensemble

Je l'ai essayé dans une application de test, et cela a fonctionné à merveille - mais quand je l'ai inclus dans mon application principale actuelle, il est tombé en panne. Lorsque vous essayez de faire l'appel d'insertion en bloc réelle, le système se bloque avec une exception:

BulkInsertProviderNotFoundException: BulkInsertProvider pas trouvé pour « Glimpse.Ado.AlternateType.GlimpseDbConnection. Pour enregistrer une nouvelle méthode EntityFramework.BulkInsert.ProviderFactory.Register() utilisation du fournisseur »

Maintenant, je ne suis pas sûr si cela est la faute de Glimpse ou EF BulkInsert (ou les deux), et malheureusement, je n'arrive pas à trouver une solution - aucun des fabricants de ces logiciels ne fournit d'idées ou de solutions de contournement.

Est-ce que quelqu'un ici a trébuché sur ce même problème, et a trouvé une solution pour cela?

Répondre

6

Ce problème se produit parce que Glimpse enveloppe DbConnection et EF BulkInsert l'extension tente d'accéder à son domaine privé « _connectionString » qui est pas là. Je blâmerais EF BulkInsert dans ce cas comme l'accès aux membres privés est juste une mauvaise pratique et aucun développeur de l'équipe Glimpse n'aurait pu prévoir cela.

Pour résoudre ce problème, je l'ai écrit une coutume qui hérite de EfSqlBulkInsertProviderWithMappedDataReader (fournisseur par défaut):

public class GlimpseProvider : EfSqlBulkInsertProviderWithMappedDataReader, IEfBulkInsertProvider 
    { 

     private static object GetPrivateFieldValue(object obj, string propName) { 
      if (obj == null) throw new ArgumentNullException("obj"); 
      Type t = obj.GetType(); 
      FieldInfo fieldInfo = null; 
      PropertyInfo propertyInfo = null; 
      while (fieldInfo == null && propertyInfo == null && t != null) { 
       fieldInfo = t.GetField(propName, 
        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
       if (fieldInfo == null) { 
        propertyInfo = t.GetProperty(propName, 
         BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
       } 

       t = t.BaseType; 
      } 
      if (fieldInfo == null && propertyInfo == null) 
       throw new ArgumentOutOfRangeException("propName", 
        string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName)); 

      if (fieldInfo != null) 
       return fieldInfo.GetValue(obj); 

      return propertyInfo.GetValue(obj, null); 
     } 

     protected override IDbConnection DbConnection { 
      get { return (IDbConnection)GetPrivateFieldValue(this.Context.Database.Connection, "InnerConnection"); } 
     } 
    } 

Enregistrez-vous maintenant ce fournisseur quelque part. Je l'ai fait en contexte Méthode OnModelCreating.

EntityFramework.BulkInsert.ProviderFactory.Register<GlimpseProvider>("Glimpse.Ado.AlternateType.GlimpseDbConnection"); 

Sachez que je l'ai testé ce uniquement avec l'utilisation de base de EF BulkInsert.

+1

Merci beaucoup - fonctionne comme un charme! –

+0

Merci, c'était vraiment utile! –