将一对一转换为一对多关系问题

我在将一对一关系更改为一对多关系时遇到了一些极端困难,而无需完全清除数据库并重新开始(我无法合理地对生产数据库执行此操作)。启用自动迁移的实体框架 6(也无法更改此设置)。


原始数据库模式要求这些类之间存在一对一的关系(不相关的属性已被删除):


public class Job

    {

        [Key]

        public int JobIb { get; set; }


        public virtual JobSite Location { get; set; }

    }

public class JobSite

    {

        [Key]

        [ForeignKey("Job")]

        public int JobSiteID { get; set; }


        [Required]

        public virtual Job Job { get; set; }

    }

随后,需求更改为一对多(一个 JobSite 可以有多个 Job)


public class Job

    {

        [Key]

        public int JobIb { get; set; }


        public virtual JobSite Location { get; set; }

    }

public class JobSite

    {

        [Key]

        public int JobSiteID { get; set; }


        public virtual ICollection<Job> Jobs { get; set; }

    }

这与EntityFrameworkTutorial上的约定 #3和Microsoft 的导航属性示例相匹配。

第一种方法进一步向下移动以进行归档。长话短说,您不能将现有列设为标识列

我的下一个方法是在一次迁移中完全删除 JobSites 表以及与 Job 表的关系,然后在第二次迁移中重新建立它们:

这里的重点是为什么后续更新不会触发EF认为模型与数据库一致......

步骤1

public override void Up()

        {

            DropForeignKey("dbo.JobSites", "JobSiteID", "dbo.Jobs");

            DropIndex("dbo.JobSites", new[] { "JobSiteID" });

            DropTable("dbo.JobSites");

        }


        public override void Down()

        {

            CreateTable(

                "dbo.JobSites",

                c => new

                    {

                        JobSiteID = c.Int(nullable: false),

                    })

                .PrimaryKey(t => t.JobSiteID);


            CreateIndex("dbo.JobSites", "JobSiteID");

            AddForeignKey("dbo.JobSites", "JobSiteID", "dbo.Jobs", "JobIb");

        }


最初这是有效的。但是,如果我删除本地数据库,并提取生产数据库的新副本,并运行步骤 1 和步骤 2 迁移的更新数据库,则会收到 System.InvalidOperationException 错误:&ldquo;自创建数据库以来,支持&ldquo;ApplicationDbContext&rdquo;上下文的模型已更改。


所以这非常令人沮丧。如果我添加迁移临时,以查看它认为模型中发生了什么变化,我会得到与最初所做的完全相同的脚手架,就像它没有注册第 1 步和第 2 步迁移一样。


慕神8447489
浏览 126回答 1
1回答

繁星淼淼

我终于找到了解决办法。请记住,该项目正在使用自动迁移。基本上,Step1 和 Step2 迁移方法已步入正轨,但是,在 Step1 和 Step2 之后应用了第三种自动迁移。我删除了 Step2 迁移,实质上将其变成了自动迁移。当 update-database 运行时,它只应用 Step1,然后检查模型,自动创建 Step2 的内容并运行它们,欺骗其他开发人员的机器使模型和数据库重新保持一致。public partial class ResetJobSites : DbMigration&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public override void Up()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DropForeignKey("dbo.JobSites", "JobSiteID", "dbo.Jobs");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DropIndex("dbo.JobSites", new[] { "JobSiteID" });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DropTable("dbo.JobSites");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public override void Down()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateTable(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "dbo.JobSites",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c => new&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JobSiteID = c.Int(nullable: false),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .PrimaryKey(t => t.JobSiteID);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateIndex("dbo.JobSites", "JobSiteID");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AddForeignKey("dbo.JobSites", "JobSiteID", "dbo.Jobs", "JobIb");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }PM> update-databaseSpecify the '-Verbose' flag to view the SQL statements being applied to the target database.Applying explicit migrations: [201907291444500_ResetJobSites].Applying explicit migration: 201907291444500_ResetJobSites.Applying automatic migration: 201907291528423_AutomaticMigration.PM>&nbsp;总结一下:要在打开自动迁移时将一对一转换为一对多关系,您需要保留生产数据库(但愿意接受正在转换的表上的数据丢失)。创建显式迁移以解耦两个表(我通过注释掉类、Job 表上的 nav 属性、DbContext 中的 DbSet 以及构建项目所需的任何其他内容来实现此目的)。进行更改模型,将 nav 属性添加回 Job 表(ICollection nav 属性),将 DbSet 添加回 DbContext,然后让自动迁移运行。首先不要让自己陷入这种境地。
打开App,查看更多内容
随时随地看视频慕课网APP