添加一个没有App.Config的DbProviderFactory

我在我的数据层(基于entity framework)使用DbProviderFactories和我的数据库使用SQLite,但我不必有一个App.Config具有以下代码:

<configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite"/> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> </DbProviderFactories> </system.data> </configuration> 

相反,我想让我的数据层以编程方式。 任何人都知道如何做到这一点?

编辑:

原因是我正在使用一个IoC容器来select数据层,而我的一些数据层不需要App.Config值,或者让它们与数据层紧密相连。

下面可能会引起太阳黑子,推翻西方文明。 它甚至可能引起关于Duct Tape编程的争论(让它停止!),但它工作(现在)

 try { var dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet; dataSet.Tables[0].Rows.Add("SQLite Data Provider" , ".Net Framework Data Provider for SQLite" , "System.Data.SQLite" , "System.Data.SQLite.SQLiteFactory, System.Data.SQLite"); } catch (System.Data.ConstraintException) { } 

上面的JoshRivers发布了SQLite解决scheme。 这实际上也可以用于其他适配器 – 我可以用他的例子为MySQL工作。 我把这个包装成了一个更通用的东西。 这应该在应用程序启动后运行,并且适用于.NET连接器版本6.6.5.0(但是我认为它也适用于其他版本)。

 string dataProvider = @"MySql.Data.MySqlClient"; string dataProviderDescription = @".Net Framework Data Provider for MySQL"; string dataProviderName = @"MySQL Data Provider"; string dataProviderType = @"MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.6.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"; bool addProvider = true; var dataSet = ConfigurationManager.GetSection("system.data") as DataSet; foreach (DataRow row in dataSet.Tables[0].Rows) { if ((row["InvariantName"] as string) == dataProvider) { // it is already in the config, no need to add. addProvider = false; break; } } if (addProvider) dataSet.Tables[0].Rows.Add(dataProviderName, dataProviderDescription, dataProvider, dataProviderType); 

select数据库提供程序工厂程序化几乎失败的目的。 你不如使用特定于SQLite的类而不是所有这些接口,不是吗?

晚答案:

你总是可以直接得到这样一个工厂:

 DbProviderFactory factory = System.Data.SQLite.SQLiteFactory.Instance; // (note that the rest of the code is still provider-agnostic.) 

或者使用你的IoC容器来parsingDbProviderFactory ,例如:

 container.RegisterInstance<DbProviderFactory>(SQLiteFactory.Instance); 

我更喜欢使用DbProviderFactories.GetFactory因为它需要一个configuration文件的限制(或像JoshRiver的答案中的黑客)。

所有DbProviderFactories.GetFactory所做的是,它使用提供程序名称查找工厂types的已注册程序集限定名称,然后使用reflection来获取静态Instance属性的值。

如果你不想使用configuration,根据你的使用情况,上面的方法可能会更方便一些。

更新EF 6.0+

您可以通过注册IDbDependencyResolver并parsingDbProviderFactorytypes来添加DbProviderFactory 。 下面是一个例子:

 static class Program { [STAThread] static void Main() { System.Data.Entity.DbConfiguration.Loaded += (_, a) => { a.AddDependencyResolver(new MyDependencyResolver(), true); }; Application.Run(new Form1()); } } class MyDependencyResolver : System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver { public object GetService(Type type, object key) { // Output the service attempting to be resolved along with it's key System.Diagnostics.Debug.WriteLine(string.Format("MyDependencyResolver.GetService({0}, {1})", type.Name, key == null ? "" : key.ToString())); if (type == typeof(System.Data.Common.DbProviderFactory)) { // Return whatever DbProviderFactory is relevant return new MyDbProviderFactory(); }else if(type == typeof(System.Data.Entity.Infrastructure.IProviderInvariantName) && key != null && key == "MyDbProviderFactory"){ // Return the Provider's invariant name for the MyDbProviderFactory return new MyProviderInvariantName(); } return null; } public IEnumerable<object> GetServices(Type type, object key) { return new object[] { GetService(type, key) }.ToList().Where(o => o != null); } } 

您可能还需要解决一些其他types的问题,具体取决于您需要执行的重要types以及如何设置项目。 基本上只是从上面的代码开始,并继续debugging,直到您确定了所有需要解决的服务,以满足您的特定需求。

您可以在以下链接阅读更多关于EF依赖关系parsing的信息:

此外,您可以通过覆盖DbConfiguration来执行此configuration,如上面第一个链接中所述。

甚至后来的答案

得到它使用像上面的configuration。 我发现这似乎要求运行程序可以find它的地方。

  /// <summary> /// Creates a DbProviderFactory instance without needing configuration file /// </summary> /// <param name="lsProviderName">Name of the provider. Like "System.Data.SQLite"</param> /// <param name="lsClass">Class and assembly information. Like "System.Data.SQLite.SQLiteFactory, System.Data.SQLite"</param> /// <returns>A specific DbProviderFactory instance, or null if one can't be found</returns> protected static DbProviderFactory GetDbProviderFactoryFromConfigRow(string lsProviderName, string lsClass) { if (string.Empty != lsProviderName && string.Empty != lsClass) { DataRow loConfig = null; DataSet loDataSet = ConfigurationManager.GetSection("system.data") as DataSet; foreach (DataRow loRow in loDataSet.Tables[0].Rows) { if ((loRow["InvariantName"] as string) == lsProviderName) { loConfig = loRow; } } if (null == loConfig) { loConfig = loDataSet.Tables[0].NewRow(); loConfig["InvariantName"] = lsProviderName; loConfig["Description"] = "Dynamically added"; loConfig["Name"] = lsProviderName + "Name"; loConfig["AssemblyQualifiedName"] = lsClass; loDataSet.Tables[0].Rows.Add(loConfig); } try { DbProviderFactory loDbProviderFactoryByRow = DbProviderFactories.GetFactory(loConfig); return loDbProviderFactoryByRow; } catch (Exception loE) { //// Handled exception if needed, otherwise, null is returned and another method can be tried. } } 

另一种直接从程序集中获取实例字段的方法。 即使DLL在系统的其他地方,它也能正常工作。

  /// <summary> /// Creates a DbProviderFactory instance without needing configuration file /// </summary> /// <param name="lsClass">Class and assembly information. Like "System.Data.SQLite.SQLiteFactory, System.Data.SQLite"</param> /// <param name="lsAssemblyFile">Full path to the assembly DLL. Like "c:\references\System.Data.SQLite.dll"</param> /// <returns>A specific DbProviderFactory instance, or null if one can't be found</returns> protected static DbProviderFactory GetDbProviderFactoryFromAssembly(string lsClass, string lsAssemblyFile) { if (lsAssemblyFile != string.Empty && lsClass != string.Empty) { Assembly loAssembly = System.Reflection.Assembly.LoadFrom(lsAssemblyFile); if (null != loAssembly) { string[] laAssembly = lsClass.Split(new char[] { ',' }); Type loType = loAssembly.GetType(laAssembly[0].Trim()); FieldInfo loInfo = loType.GetField("Instance"); if (null != loInfo) { object loInstance = loInfo.GetValue(null); if (null != loInstance) { if (loInstance is System.Data.Common.DbProviderFactory) { return loInstance as DbProviderFactory; } } } } } return null; } 

看到下面的片段

  public DataProviderManager(string ProviderName) { var _Provider = DbProviderFactories.GetFactory(ProviderName); } 

你需要传递你的情况是“System.Data.SQLite”的ProviderName。

你不需要创build应用程序configuration部分。 SQLite.net提供程序安装后,该部分由machine.config中的SQLite创build。

appconfig部分的全部目的是在您调用以下命令时帮助您获取configuration的.net提供程序的列表:

public GetProvidersList(){DataTable table = DbProviderFactories.GetFactoryClasses(); }

看到这里的例子: MSDN:获取DbProviderFactory