SQLite with Entity Framework 6"没有这样的表"

时间:2017-02-01 10:12:20

标签: c# entity-framework sqlite

我首先尝试使用 SQLite EntityFramework 6 代码实施this question。我可以创建数据库并且有一个文件(虽然是空的),但是当我尝试向数据库添加一个条目时,它说没有这样的表。然而,当我尝试手动创建表(db.Database.ExecuteSqlCommand("CREATE TABLE etc.))时,它告诉我表已经存在。

我已经发现了一些关于此问题的问题,但他们都认为道路不是绝对的,这根本就不是这样。

上下文

//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)
    {

    }        
}

DAL

//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中

//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>

5 个答案:

答案 0 :(得分:5)

EF6的SQLite提供程序不支持“代码优先/迁移”工作流,因此您必须在EF6工作流之外手动创建数据库。

答案 1 :(得分:2)

就像ErikEJ所说的那样,SQLite不会首先支持我使用它的代码,显然它有一个严格的命名策略。

为了完成所有工作,我必须手动创建表,并使上下文适应命名模式(Media =&gt; MediaModels)。

上下文

public DbSet<MediaModel> MediaModels { get; set; }

DAL

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();
    }
}

该代码仍然不完美,我会在改进时尝试更新此答案。

答案 2 :(得分:2)

我有Code First方法的工作灵感来自这篇文章:
Create SQLite DB using Entity Framework Core Code First

诀窍是在上下文构造函数中调用EnsureCreated:

    public MediaContext()
    {
        Database.EnsureCreated();
    }

关于属性名称匹配的表名:
您可以使用Table属性来完成工作:

public DbSet<MediaModel> Media { get; set; }

并在模型类中显式指定表名,尽管这似乎是多余的:

[Table("MediaModel")]
public class MediaModel

答案 3 :(得分:0)

我正在使用.NET Core和EntityFramework Core 2,并为SQLite进行了代码优先迁移。 在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);
    }

另一个选择-TableAttribute也应该有所帮助:

    [Table("Files")]
    public class File
    {
        // ...
    }

OnModelCreating将覆盖TableAttribute中指定的表名。

答案 4 :(得分:0)

这是来自Microsoft itself的建议答复:

  

在运行.NET时,Visual Studio使用不一致的工作目录   核心控制台应用程序。 (请参阅dotnet / project-system#3619)   引发异常:no such table: Blogs.更新工作   目录:

     

右键单击项目,然后选择“编辑项目文件”

     

在TargetFramework属性下方,添加以下内容:

     

<StartWorkingDirectory>$(MSBuildProjectDirectory)</StartWorkingDirectory>

     

保存文件

     

现在您可以运行该应用了:

     

Debug>不调试就开始