【问题标题】:EF using code first with existing tableEF 首先使用代码和现有表
【发布时间】:2016-06-06 23:23:21
【问题描述】:

我正在使用 MVC5 和 EF6。我正在做代码优先的方法。我有一些需要使用迁移(工作)生成的表和一些我需要从现有数据库中使用的表 - 表。

在我的 DbContext 类中

    'new table that is created in the DB (works)  
    public DbSet<Subscription> Subscriptions { get; set; }
    public DbSet<Memeber> Members { get; set; }
    'existing table. 
    public DbSet<CodeTable> CodeTable { get; set; }

在配置-(迁移文件夹)中

    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

它现在做了什么,它创建了一个名为 CodeTables 的新表

  1. 变成复数了,这是为什么呢?- 可以关掉吗?
  2. 如何使用CodeTable而不生成新表?
  3. 当我手动删除使用 codefirst 生成的表时,即成员表。然后我运行

Update-Database -Verbose -Force(什么都不做)
使用启动项目“测试”。
使用 NuGet 项目“测试”。
指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。
目标数据库是:'TESTDB'(数据源:10.10.50.89,提供者:
System.Data.SqlClient,来源:配置)。
没有待处理的显式迁移。
运行种子方法。

然后运行应用程序,我得到一个异常
System.Data.SqlClient.SqlException (0x80131904):无效的对象名称“dbo.Members”。在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常

因为找不到表。没有生成表。

如果找不到表,我如何让它知道。创建它?

我注意到如果我删除 __MigrationHistory 然后运行更新数据库。然后它抱怨我存在的其他表
数据库中已经有一个名为“订阅”的对象。
只有在我删除所有表格时它才有效。但这似乎很愚蠢,删除所有表。我希望有另一种方法。

【问题讨论】:

    标签: asp.net-mvc entity-framework ef-code-first entity-framework-6 entity-framework-migrations


    【解决方案1】:

    要首先对现有数据库使用代码,您需要做两件事:1) 指定连接字符串和 2) 关闭数据库初始化策略。这两件事可以通过以下上下文示例来实现:

    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext()
            : base("ConnectionStringName")
        {
            Database.SetInitializer<ApplicationDbContext>(null);
        }
    
        // DbSets here
    }
    

    现在,按照惯例,Entity Framework 假定您的表名是实体类名的复数形式。如果表名不是复数和/或它与实体类名不同,那么您可以使用Table 属性来准确指定它应该是什么:

    [Table("foo_table")]
    public class Foo
    {
        // properties
    }
    

    同样,如果您的列名与您的属性名不匹配,您可以使用Column 属性来指定:

    [Column("strFoo")]
    public string Foo { get; set; }
    

    更新

    在第一次阅读时,我没有注意到您正在尝试将现有表与代码生成的表混合和匹配。你不能做这个。由于使用现有数据库/现有表需要禁用初始化策略,要么该数据库中的所有表都必须存在,要么实体框架必须生成所有表。你不能半途而废。

    如果您需要利用一些现有表并让 EF 创建一些表,则需要两个数据库和两个上下文,一个是 EF 将首先通过代码生成所有内容,另一个是关闭初始化策略并由您负责数据库和表。重要的是,这意味着您不能混合和匹配这些。您的所有代码优先实体都不能通过导航属性引用您现有的任何数据库实体,否则它们将被隐式添加到代码优先上下文中,EF 将生成表。

    您可以做的最好的事情是拥有一个保存相关实体 id 的常规属性,然后手动使用此 id 从现有的数据库上下文中查找实体。换句话说,它不是真正的外键,你将无法利用延迟加载等。

    【讨论】:

    • 感谢克里斯为我清理一切。由于我无法混搭,请您善待并帮助我理解我的 Q#3。假设我想首先为 EF 使用代码为我生成表。如果我手动删除一个表,是否需要删除所有其他表,包括 MigrationHistory 表才能运行更新数据库?或者我将如何告诉 EF 创建我删除的那个。
    • 如果你要让 EF 管理你的数据库,那么你必须让它管理数据库。换句话说,您不能只是进入数据库并手动删除或更改表。数据库的状态在迁移历史记录中进行了编码,除非 EF 运行迁移以进行更改,否则它不知道您自己手动执行了什么操作。如果您删除 _MigrationHistory 表,那只会让 EF 不再关心数据库是否不同步,但是您将无法使用 EF 进行任何其他迁移。
    • 总之,您需要恢复所做的任何更改或删除数据库和所有迁移并重新开始。然后,仅通过您的代码进行修改。
    【解决方案2】:

    我的做法不同——我用我需要的所有表创建一个大型上下文——并在该上下文上进行迁移/数据库更新。然后创建几个“只读”上下文——在我称之为Database.SetInitializer(null) 的意义上——意味着它们不会进行迁移等——并在那里只添加必要的DbSet。这样我就可以完全实现你所描述的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-10
      • 2017-01-17
      • 2014-07-06
      • 2020-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多