[英]SQLite with Entity Framework 6 “no such table”
I'm trying to implement this question with SQLite and EntityFramework 6 code first.我试图首先用SQLite和EntityFramework 6代码来实现这个问题。 I can create the database and there is a file (although empty), but when I try to add an entry to the database it says there is no such table.我可以创建数据库并且有一个文件(虽然是空的),但是当我尝试向数据库添加一个条目时,它说没有这样的表。 Yet, when I try to create the table manually ( db.Database.ExecuteSqlCommand("CREATE TABLE etc.)
) it tells me that the table already exists.然而,当我尝试手动创建表( db.Database.ExecuteSqlCommand("CREATE TABLE etc.)
)时,它告诉我该表已经存在。
I found some questions about this already, but they're all about the path not being absolute, which is simply not the case here.我已经发现了一些关于此的问题,但它们都是关于路径不是绝对的,这里的情况并非如此。
//Context:
class MediaContext : DbContext
{
public DbSet<MediaModel> Media { get; set; }
public MediaContext(string filename): base(new SQLiteConnection() {
ConnectionString =
new SQLiteConnectionStringBuilder()
{ DataSource = filename, ForeignKeys = false }
.ConnectionString
}, true)
{
}
}
//In the DAL:
public DataAccessLayer(string path)
{
_path = Path.GetFullPath(path); //<--The path already comes full in, I'm just paranoid at this point.
_connectionPath = _path + @"\MyDatabase.sqlite";
using (var db = new MediaContext(_connectionPath))
{
db.Database.CreateIfNotExists();
db.Database.Initialize(false);
db.SaveChanges();
}
public void Generate()
{
using (var db = new MediaContext(_connectionPath))
{
db.Media.Add(new MediaModel("test"));
db.SaveChanges(); //<--SQLiteException: SQL logic error or missing database: no such table: MediaModels
}
}
//App.config:
<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>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v13.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<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.EF6" />
<add name="SQLite Data Provider" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
</system.data>
</configuration>
I have got Code First approach working inspired by this post:受这篇文章的启发,我得到了 Code First 方法的启发:
Create SQLite DB using Entity Framework Core Code First 首先使用 Entity Framework Core Code 创建 SQLite DB
The trick is to have a call to EnsureCreated in the context constructor:诀窍是在上下文构造函数中调用确保创建:
public MediaContext()
{
Database.EnsureCreated();
}
Regarding the table name to property name matching:关于表名到属性名匹配:
You can use the Table
attribute to make things work:您可以使用Table
属性来使事情工作:
public DbSet<MediaModel> Media { get; set; }
and explicitly specify the table name in your model class although this seems redundant:并在您的模型类中明确指定表名,尽管这似乎是多余的:
[Table("MediaModel")]
public class MediaModel
EF6 的 SQLite 提供程序不支持 Code First/Migrations 工作流,因此您必须在 EF6 工作流之外手动创建数据库。
This is the recommended reply from Microsoft itself :这是微软自己推荐的回复:
Visual Studio uses an inconsistent working directory when running .NET Core console apps. Visual Studio 在运行 .NET Core 控制台应用程序时使用不一致的工作目录。 (see dotnet/project-system#3619) This results in an exception being thrown:
no such table: Blogs.
(请参阅 dotnet/project-system#3619)这会导致抛出异常:no such table: Blogs.
To update the working directory:要更新工作目录:Right-click on the project and select Edit Project File右键单击项目并选择编辑项目文件
Just below the TargetFramework property, add the following:在 TargetFramework 属性下方,添加以下内容:
<StartWorkingDirectory>$(MSBuildProjectDirectory)</StartWorkingDirectory>
Save the file保存文件
Now you can run the app:现在您可以运行该应用程序:
Debug > Start Without Debugging调试 > 在不调试的情况下启动
Like ErikEJ said does SQLite not support code first in they way I use it, and apparently it has a strict naming policy.就像 ErikEJ 所说的那样,SQLite 不以我使用它的方式首先支持代码,而且显然它有严格的命名策略。
To make it all work I had to manually create the table, and adapt the context to the naming schema ( Media
=> MediaModels
).为了使这一切正常工作,我必须手动创建表,并使上下文适应命名模式( Media
=> MediaModels
)。
public DbSet<MediaModel> MediaModels { get; set; }
public DataAccessLayer(string path)
{
_path = Path.GetFullPath(path);
_connectionPath = _path + @"\MyDatabase.sqlite";
using (var db = new MediaContext(_connectionPath))
{
db.Database.ExecuteSqlCommand("CREATE TABLE IF NOT EXISTS 'MediaModels' ('Name' TEXT, 'FilePath' TEXT NOT NULL PRIMARY KEY, 'Tags' TEXT, 'Note' TEXT, 'FileExtension' TEXT)");
db.SaveChanges();
}
}
public void Generate()
{
using (var db = new MediaContext(_connectionPath))
{
db.MediaModels.Add(new MediaModel("test"));
db.SaveChanges();
}
}
That code is still not perfect, and I'll try to update this answer as I improve it.该代码仍然不完美,我会在改进它时尝试更新此答案。
I'm using .NET Core and EntityFramework Core 2 and code first migration for SQLite.我正在使用 .NET Core 和 EntityFramework Core 2 并为 SQLite 进行代码优先迁移。 Specifying table name in OnModelCreating
helped to solve the issue:在OnModelCreating
指定表名有助于解决问题:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<File>()
.ToTable(typeof(File).Name + "s") // <-- the argument could be just "Files"
.HasKey(lf => new { lf.MachineName, lf.PathName });
base.OnModelCreating(modelBuilder);
}
Another option - TableAttribute
also should have helped:另一个选项 - TableAttribute
也应该有帮助:
[Table("Files")]
public class File
{
// ...
}
OnModelCreating
will override table name specified in TableAttribute
if both are specified.如果两者都被指定, OnModelCreating
将覆盖TableAttribute
中指定的表名。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.