EF7(Code First)+ SQLite无法为模型创建数据库和表

5

我目前正试图使用EF7和SQLite创建Universal Windows Platform应用程序,以重现文档http://ef.readthedocs.org/en/latest/getting-started/uwp.html中所示的示例。

我已安装所需的EF7和EF7 Commands包,并创建了模型和上下文:

 public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
            string dirPath = ApplicationData.Current.LocalFolder.Path;
            string connectionString = "Filename=" + Path.Combine(dirPath, "blogging.db");
            optionsBuilder.UseSqlite(connectionString);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

我的问题是,在构建解决方案之后,应该生成迁移命令以创建模型的初始表集,但是该命令失败,并出现以下异常:

PM> Add-Migration MyFirstMigration
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
 at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
 at System.Reflection.RuntimeAssembly.get_DefinedTypes()
 at Microsoft.Data.Entity.Design.Internal.StartupInvoker..ctor(String startupAssemblyName, String environment)
 at Microsoft.Data.Entity.Design.DbContextOperations..ctor(ILoggerProvider loggerProvider, String assemblyName, String startupAssemblyName, String environment)
 at Microsoft.Data.Entity.Design.MigrationsOperations..ctor(ILoggerProvider loggerProvider, String assemblyName, String startupAssemblyName, String environment, String projectDir, String rootNamespace)
 at Microsoft.Data.Entity.Design.OperationExecutor.<>c__DisplayClass3_0.<.ctor>b__3()
 at Microsoft.Data.Entity.Internal.LazyRef`1.get_Value()
 at Microsoft.Data.Entity.Design.OperationExecutor.<AddMigrationImpl>d__7.MoveNext()
 at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
 at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
 at Microsoft.Data.Entity.Design.OperationExecutor.OperationBase.<>c__DisplayClass4_0`1.<Execute>b__0()
 at Microsoft.Data.Entity.Design.OperationExecutor.OperationBase.Execute(Action action)
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

有人有解决这个问题的方案吗? 提前感谢。

你尝试过不指定完整路径名吗?就像你链接到的页面上的例子一样? - Rowland Shaw
1
你的应用程序是否使用了任何Windows Runtime组件?你看到的错误看起来几乎与https://github.com/aspnet/EntityFramework/issues/3543相同。 - natemcmaster
谢谢您的回复,@natemcmaster。它可以在普通类库中使用,但如果它与通用Windows应用程序不兼容,我该如何使用它? - fhin
EF与UWP兼容。WinRT组件与UWP或.NET类库不同。 - natemcmaster
正如这里的一个答案所述,https://dev59.com/3JDea4cB1Zd3GeqPgMRF?rq=1,在UWP上似乎无法从命令中运行迁移。您需要在应用程序中运行它们。但在我的情况下,即使我尝试访问它,也无法工作,因为我会收到表不存在的异常。 - fhin
1个回答

5
在我的情况下,解决问题的方法是在应用程序启动之前通过代码在app.xaml中创建数据库和表。
using (var db = new BloggingContext())
{
    db.Database.EnsureCreated();
    db.Database.Migrate();
}

上下文 + 模型:

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        string path = ApplicationData.Current.LocalFolder.Path;
        if (!File.Exists(Path.Combine(path, "blogging.db")))
        {
            File.Create(Path.Combine(path, "blogging.db"));
        }
        optionsBuilder.UseSqlite("Data Source=" + Path.Combine(path, "blogging.db")+";");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Make Blog.Url required
        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .IsRequired();
    }
}

[Table("Blog")]
public class Blog
{
    [Key]
    public int BlogId { get; set; }
    [MaxLength(100)]
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

[Table("Post")]
public class Post
{
    [Key]
    public int PostId { get; set; }

    [MaxLength(30)]
    public string Title { get; set; }
    [MaxLength(250)]
    public string Content { get; set; }

    public int BlogId { get; set; }
    [ForeignKey("BlogId")]
    public Blog Blog { get; set; }
}

在访问数据库之前,我会确保它已经被创建了,例如:

 using (var db = new BloggingContext())
 {
     db.Database.EnsureCreated();
     Blogs.ItemsSource = db.Blogs.ToList();
 }

2
警告,Migrate() 方法使用迁移,而 EnsureCreated 不使用。它们是互斥的。 - user4856537

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接