我用我的数据层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容器来接数据层和我的一些数据层的不需要App.Config中值,或让他们很难依赖于数据层。
Answer 1:
以下可能会导致太阳黑子和推翻西方文明。 它甚至可能导致约管道胶带编程(让它停下!)争论,但它的工作原理(现在)
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) { }
Answer 2:
以上JoshRivers发布为SQLite的溶液。 这其实也可以用于其他的适配器为良好,我能够得到它为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);
Answer 3:
迟到的回答:
你总是可以直接获得一个工厂是这样的:
DbProviderFactory factory = System.Data.SQLite.SQLiteFactory.Instance;
// (note that the rest of the code is still provider-agnostic.)
或使用IoC容器来解决DbProviderFactory
,如:
container.RegisterInstance<DbProviderFactory>(SQLiteFactory.Instance);
我不喜欢使用的DbProviderFactories.GetFactory
,因为它需要(或一劈像一个配置文件的限制@ JoshRiver的答案 )。
所有DbProviderFactories.GetFactory
确实是,它查找使用提供者的名称工厂类型的注册程序集限定名称 ,然后它得到的静态值Instance
使用反射特性。
如果你不想使用的配置,方法之一以上可能会因你的使用情况更加方便。
Answer 4:
更新EF 6.0+
您可以添加一个DbProviderFactory
通过注册IDbDependencyResolver
和解决的类型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);
}
}
您可能需要解析以及根据什么类型的覆盖你需要做的,是如何的项目是设置一些其他类型。 基本上,刚开始用上面的代码并继续调试,直到你确定你需要解决给定您的特定需求的所有服务。
你可以阅读更多关于下面的链接EF依赖解析:
- http://msdn.microsoft.com/en-us/data/jj680697.aspx
- https://entityframework.codeplex.com/wikipage?title=EF%20Configuration%20and%20Extensibility
- https://entityframework.codeplex.com/wikipage?title=Rebuilding%20EF%20providers%20for%20EF6
此外,还可以通过重写做到这一点的配置DbConfiguration
如上面的第一个链接描述。
Answer 5:
艇员选拔的DB提供程序的工厂几乎失败的目的。 你还不如使用特定于SQLite的,而不是所有这些接口的类的,不是吗?
Answer 6:
看看下面的代码片段
public DataProviderManager(string ProviderName)
{
var _Provider = DbProviderFactories.GetFactory(ProviderName);
}
你需要传递的ProviderName你的情况是“System.Data.SQLite”。
你不需要创建应用程序配置部分。 该节被安装SQLite.net提供商后在machine.config SQLite创建。
了AppConfig节的整个目的是帮助你,当你调用下面的命令配置.NET提供的名单:
公共GetProvidersList(){数据表表= DbProviderFactories.GetFactoryClasses(); }
Answer 7:
即使后来回答
获取使用配置像上面吧。 我发现,这似乎要求提供组装是地方,正在运行的程序可以找到它。
/// <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;
}
Answer 8:
在.NET核心2.1及更高版本,您可以使用DbProviderFactories.RegisterFactory
以编程方式注册DbProviderFactory
。
文章来源: Add a DbProviderFactory without an App.Config