【异常处理】无法将类型为“Glimpse.Ado.AlternateType.GlimpseDbConnection”的对象强制转换为类型“System.Data.SqlClient.SqlConnection”。

解决了一个棘手的EF框架引入问题,所以做下记录。

最近在集成EF到现有系统中,由于现有系统比较旧,调用ToList的时候就会报这个错误

错误代码

var file = _ctx.FileInfo.FirstOrDefault(t => t.ID == uid);

报错信息

Unable to determine the provider name for provider factory of type 'System.Data.SqlClient.SqlClientFactory'. Make sure that the ADO.NET provider is installed or registered in the application config.

无法将类型为“Glimpse.Ado.AlternateType.GlimpseDbConnection”的对象强制转换为类型“System.Data.SqlClient.SqlConnection”。

堆栈1

System.NotSupportedException: Unable to determine the provider name for provider factory of type 'System.Data.SqlClient.SqlClientFactory'. Make sure that the ADO.NET provider is installed or registered in the application config. 
在 System.Data.Entity.Utilities.DbProviderFactoryExtensions.GetProviderInvariantName(DbProviderFactory factory)
在 System.Data.Entity.Infrastructure.DependencyResolution.DefaultInvariantNameResolver.GetService(Type type, Object key)
在 System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
在 System.Data.Entity.Infrastructure.DependencyResolution.RootDependencyResolver.GetService(Type type, Object key)
在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
在 System.Data.Entity.Infrastructure.DependencyResolution.CompositeResolver`2.GetService(Type type, Object key)
在 System.Data.Entity.Infrastructure.DependencyResolution.DbDependencyResolverExtensions.GetService[T](IDbDependencyResolver resolver, Object key)
在 System.Data.Entity.Utilities.DbConnectionExtensions.GetProviderInvariantName(DbConnection connection)
在 System.Data.Entity.Internal.InternalConnection.get_ProviderName()
在 System.Data.Entity.Internal.DefaultModelCacheKeyFactory.Create(DbContext context)
在 System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
在 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
在 System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
在 System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
在 System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
在 UFSoft.UBF.MVC.MainController.TestEF(String uid)

堆栈2

System.InvalidCastException: 无法将类型为“Glimpse.Ado.AlternateType.GlimpseDbConnection”的对象强制转换为类型“System.Data.SqlClient.SqlConnection”。 
在 System.Data.SqlClient.SqlCommand.set_DbConnection(DbConnection value)
在 System.Data.Entity.Core.Common.Utils.CommandHelper.SetStoreProviderCommandState(EntityCommand entityCommand, EntityTransaction entityTransaction, DbCommand storeProviderCommand)
在 System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.PrepareEntityCommandBeforeExecution(EntityCommand entityCommand)
在 System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
在 System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
在 System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
在 System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClassb.b__9()
在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
在 System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
在 System.Data.Entity.Core.Objects.ObjectQuery`1..GetEnumerator>b__0()
在 System.Lazy`1.CreateValue()
在 System.Lazy`1.LazyInitValue()
在 System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
在 System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
在 System.Data.Entity.Migrations.History.HistoryRepository.QueryExists(String contextKey)
在 System.Data.Entity.Migrations.History.HistoryRepository.Exists(String contextKey)
在 System.Data.Entity.Migrations.History.HistoryRepository.GetLastModel(String& migrationId, String contextKey)
在 System.Data.Entity.Migrations.History.HistoryRepository.GetLastModel()
在 System.Data.Entity.Internal.ModelCompatibilityChecker.CompatibleWithModel(InternalContext internalContext, ModelHashCalculator modelHashCalculator, Boolean throwIfNoMetadata)
在 System.Data.Entity.CreateDatabaseIfNotExists`1.InitializeDatabase(TContext context)
在 System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
在 System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
在 System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)
在 System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)
在 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
在 System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
在 System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
在 System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
在 UFSoft.UBF.MVC.MainController.TestEF(String uid)
位置 G:yonyouU9CEUBFUBFADFUIUI_MVCControllerMainController.cs:行号 3402

首先看了下第一个报错

应该是配置问题导致的,所以新建了一个EF项目,看到默认的配置文件,进行对比。

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=&quot;Web&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v13.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>
  <connectionStrings>
    <add name="Model1" connectionString="data source=lijianhua;initial catalog=U9CE20210418Doc;persist security info=True;user id=sa;password=******;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

看到了连接字符串后面带一个 providerName 参数,但是我的项目里连接字符串是动态配置的,没法写到配置文件里,只能通过代码实现传入 providerName 

所以创建 DbConnection 的时候是直接 new 出来的,所以EF并不能识别这个类型。

用下面的工厂模式方式创建即可

        public static DbConnection GetConn(string connstr)
        {
            var connection = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateConnection();
            connection.ConnectionString = connstr;
            //配置了 U9_Glimpse_Allowed 才会返回此类型
            //if (UFIDA.U9.UI.PDHelper.FormAuthorityHelper.IsUserInRole("Glimpse", long.Parse(CSContext.Current.OrgId), long.Parse(CSContext.Current.UserID)))
            if (connection is GlimpseDbConnection)
            {
                return ((GlimpseDbConnection)connection).InnerConnection as SqlConnection;
            }
            return connection;
        }

但是创建完之后,发现了第二个报错。

创建出来的类型并不是我需要的 DbConnection 类型,是得到的 GlimpseDbConnection 类型,这是由于目前的老框架在这块进行了区分,这个GlimpseDbConnection 是为了分析性能而特别创建的 Connection 。但是EF并不能接收这个类型。

所以采用后面的转换方式进行转换即可正常使用。

参考文档1

http://aiuxian.com/article/p-tewsmagq-btb.html

参考文档2

百度快照

至此已经可以正常在项目里使用EF框架,进行愉快的增删改查了。

EF集成工作圆满结束!!!

每天进步一丢丢
防盗签名:本文来自【博客园】-【多安分】

恭喜兄dei,看到这个隐藏标签~~~如果觉得博客内容有所帮助,请扫二维码打赏,感谢老铁

支付宝

微信

原文地址:https://www.cnblogs.com/jhli/p/15355937.html