无App.Config配置时Rhinoceros 6插件使用EF对接SQL Server CE
Rhinoceros 6插件无配置文件场景下使用EF连接SQL Server CE的问题记录
问题背景
- 开发Rhino 6插件过程中,不具备修改Rhino宿主程序App.Config文件的权限,同时插件项目自身的App.Config配置完全不会作用于Rhino宿主的运行时配置。
- 由于无法在App.Config的
<entityFramework>配置节中添加对应的提供程序与参数配置,程序运行时抛出配置缺失报错:
无法确定类型为
System.Data.SqlServerCe.SqlCeProviderFactory的提供程序工厂对应的提供程序名称,请确认ADO.NET提供程序已安装或已在应用程序配置中注册。
前期排查
- 已通过NuGet安装
EntityFramework.SqlServer.Compact与Microsoft.SqlServer.Compact包,逐一核查所有相关程序集的引用加载状态均正常。 - 采用Code First模式编写的DbContext及实体模型核心代码如下:
public class ModelLocalClipper : DbContext { public ModelLocalClipper() : base(new SqlCeConnection("Data Source="+ Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"\\MyDatabase.sdf;Persist Security Info=False;"), contextOwnsConnection: true) { Database.SetInitializer<ModelLocalClipper>(new CreateDatabaseIfNotExists<ModelLocalClipper>()); } public DbSet<Scene> Scenes { get; set; } public DbSet<LocalProject> LocalProjects { get; set; } } public class Scene { public int SceneId { get; set; } public string Name { get; set; } public int LocalProjectId { get; set; } [ForeignKey("LocalProjectId")] public virtual LocalProject LocalProject { get; set; } } public class LocalProject { public int LocalProjectId { get; set; } public string Name { get; set; } public virtual ICollection<Scene> Scenes { get; set; } }
前期尝试
- 参考社区通用的“EF无配置文件注册提供程序”实现思路,针对SQL Server CE改写了依赖解析与提供程序注册逻辑,但仍然无法解决上述报错。
- 改写的自定义注册逻辑核心代码如下:
public class SqlCeProviderInvariantName : IProviderInvariantName { public static readonly SqlCeProviderInvariantName Instance = new SqlCeProviderInvariantName(); private SqlCeProviderInvariantName() { } public const string ProviderName = "System.Data.SqlServerCe.4.0"; public string Name { get { return ProviderName; } } } class SqlCeDbProviderFactoryResolver : IDbProviderFactoryResolver { public static readonly SqlCeDbProviderFactoryResolver Instance = new SqlCeDbProviderFactoryResolver(); private SqlCeDbProviderFactoryResolver() { } public DbProviderFactory ResolveProviderFactory(DbConnection connection) { if (connection is SqlCeConnection) return SqlCeProviderFactory.Instance; if (connection is EntityConnection) return EntityProviderFactory.Instance; return null; } } class SqlCeDbDependencyResolver : IDbDependencyResolver { public object GetService(Type type, object key) { if (type == typeof(IProviderInvariantName)) return SqlCeProviderInvariantName.Instance; if (type == typeof(DbProviderFactory)) return SqlCeProviderFactory.Instance; if (type == typeof(IDbProviderFactoryResolver)) return SqlCeDbProviderFactoryResolver.Instance; return SqlCeProviderServices.Instance.GetService(type); } public IEnumerable<object> GetServices(Type type, object key) { var service = GetService(type, key); if (service != null) yield return service; } } class SqlCeDbConfiguration : DbConfiguration { public SqlCeDbConfiguration() { AddDependencyResolver(new SqlCeDbDependencyResolver()); } }
运行环境版本
- RhinoCommon 6.30.20288.16410
- .NET Framework 4.8
- Entity Framework 6.4.4
- SQL Server CE 4.0
解决结果
- 最终按照SQL Server CE适配EF6的维护者指引完成全流程打通,无需修改Rhino宿主的任何配置文件,即可正常运行EF Code First的数据库创建、数据读写全流程。
- 整套实现整理有可直接运行的完整示例代码,可直接复用到同类插件开发场景中。
内容的提问来源于stack exchange,提问作者Tahirhan
相关产品推荐
相关产品推荐

