EF.BulkInsert和Glimpse - 不能很好地一起玩

时间:2016-07-07 14:27:23

标签: entity-framework-6 asp.net-4.5 glimpse ef-bulkinsert

我已经启动并运行了EF6 / ASP.NET 4.5 Webforms解决方案,现在我需要添加一些功能以允许从Excel文件批量插入。

我知道开箱即用的EF没有针对批量操作进行优化,因此我环顾四周并找到了“EF BulkInsert”(https://efbulkinsert.codeplex.com/)来促进这一点。

我在一个测试应用程序中尝试过,它运行得非常好 - 但是当我将它包含在我的实际主应用程序中时,它就崩溃了。尝试执行实际的批量插入调用时,系统崩溃并出现异常:

  

BulkInsertProviderNotFoundException:找不到'Glimpse.Ado.AlternateType.GlimpseDbConnection的BulkInsertProvider。要注册新的提供者,请使用EntityFramework.BulkInsert.ProviderFactory.Register()方法'

现在我不确定这是 Glimpse EF BulkInsert (或两者)的错误,不幸的是,我似乎无法找到任何解决方案 - 这些软件的制造商正在提供任何见解或解决方法......

这里有没有人偶然发现了同样的问题,并找到了解决方案?

1 个答案:

答案 0 :(得分:6)

出现此问题的原因是 Glimpse 包装DbConnection并且 EF BulkInsert 扩展程序尝试访问它的私有字段“_connectionString”,但不存在。 在这种情况下,我会责怪 EF BulkInsert ,因为访问私有成员只是不好的做法,并且Glimpse团队的开发人员都没有预料到这一点。

为了解决这个问题,我编写了一个继承自 EfSqlBulkInsertProviderWithMappedDataReader (默认提供者)的自定义:

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

现在在某个地方注册此提供商。我是在OnModelCreating方法的上下文中完成的。

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

请注意,我仅使用 EF BulkInsert 的基本用法对此进行了测试。