我试图将完整的连接字符串作为参数传递给DbContext
构造函数,我收到此错误:
无法完成操作。提供的SqlConnection不指定初始目录或AttachDBFileName。
这就是我的尝试:
public DatabaseContext() :base(@"Data Source=|DataDirectory|ComponentDatabase.sqlite") {}
问题不能与连接字符串有关,因为我能够使用App.config
中的连接字符串连接我的数据库,如下所示:
的App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<entityFramework>
<providers>
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
<connectionStrings>
<!-- use AppDomain.SetData to set the DataDirectory -->
<add name="MapDbConnectionStr" connectionString="Data Source=|DataDirectory|ComponentDatabase.sqlite" providerName="System.Data.SQLite" />
</connectionStrings>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6" />
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
<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>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.105.2" newVersion="1.0.105.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite.EF6" publicKeyToken="db937bc2d44ff139" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.105.2" newVersion="1.0.105.2" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
的DbContext
public DatabaseContext() :base("MapDbConnectionStr") {}
P.S。我知道App.config
有很多不必要的行,是的。
答案 0 :(得分:3)
据我所知,您尝试连接的数据库类型没有连接工厂。
您可以编写自己的连接工厂:
public class MySqlLiteConnectionFactory : IDbConnectionFactory
{
public DbConnection CreateConnection(string connectionString)
{
return new SQLiteConnection(connectionString);
}
}
现在去app.config中找到defaulConnectionfactory的条目,并替换指定类型的行。那时候会读到这样的东西:
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
将其更改为:
<defaultConnectionFactory type="MyNamespace.MySQLiteConnectionFactory, MyAssemblyHere" />
您现在应该能够正确使用Context ctor(string connectionString)。
还有另一种做法是不依赖于appsettings EF 6并且以后支持基于代码的配置。
所以你可以做一些看起来有点像这样的配置:
DbConfiguration.Loaded += (_, a) =>
{
a.ReplaceService<DbProviderServices>((s, k) => new MyProviderServices(s));
a.ReplaceService<IDbConnectionFactory>((s, k) => new MyConnectionFactory(s));
};
有关详细信息,请记录here at microsoft:
答案 1 :(得分:2)
使用配置文件中的名称有效,因为它可以根据提供的配置确定提供程序类型。在构造函数中直接使用连接字符串时,它无法确定连接字符串是否适用于SQLite并假设MSSQL因此它尝试使用SqlConnection
。因此,您遇到错误消息。
注意:
与数据库的连接(包括数据库的名称) 可以用几种方式指定。如果是无参数的DbContext 构造函数是从派生的上下文中调用的,然后是名称 派生上下文用于在app.config中查找连接字符串 或web.config文件。如果没有找到连接字符串,则名称为 传递给在数据库上注册的DefaultConnectionFactory 类。然后,连接工厂使用上下文名称作为 默认连接字符串中的数据库名称。 (此默认连接 字符串指向。\ SQLEXPRESS在本地计算机上除非有所不同 DefaultConnectionFactory已注册。)而不是使用派生的 上下文名称,也可以指定连接/数据库名称 显式通过将名称传递给DbContext构造函数之一 需要一个字符串。名称也可以在表单中传递 “name = myname”,在这种情况下,必须在配置文件中找到该名称 或者会抛出异常。注意在中找到的连接 app.config或web.config文件可以是普通的数据库连接 string(不是特殊的Entity Framework连接字符串) 如果DbContext将使用Code First。但是,如果连接 在配置文件中找到的是一个特殊的Entity Framework连接 字符串,然后DbContext将使用Database / Model First和模型 将使用连接字符串中指定的。现有的或 显式创建DbConnection也可以代替使用 数据库/连接名称。
Taken from the class remarks for DbContext
最后引用的句子很突出......
也可以使用现有或显式创建的DbConnection 而不是数据库/连接名称。
您可以考虑使用SQLiteConnection
public class DatabaseContext : DbContext {
public DatabaseContext()
:base(new SQLiteConnection(@"Data Source=|DataDirectory|ComponentDatabase.sqlite"), true) {
//...
}
//...
}
答案 2 :(得分:-1)
正如我所理解的那样,它可能会有所帮助,请使用带有数据库上下文选项的构建器。我使用的是SqlServer,但是应该没有太多的变化。
var builder = new DbContextOptionsBuilder<MapDbContext>();
builder.UseSqlServer(ConfigurationManager.ConnectionStrings["MapDbConnectionStr"].ConnectionString), opt => opt.EnableRetryOnFailure());
var mycontext = new MapDbContext(builder.Options);
public MapDbContext(DbContextOptions<MapDbContext> options)
: base(options)
{ }
希望它有所帮助,祝你好运。