为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
慕神8447489 2023-07-22 15:53:39
我在将一对一关系更改为一对多关系时遇到了一些极端困难,而无需完全清除数据库并重新开始(我无法合理地对生产数据库执行此操作)。启用自动迁移的实体框架 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认为模型与数据库一致......步骤1public 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 步迁移一样。
查看完整描述

1 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

我终于找到了解决办法。请记住,该项目正在使用自动迁移。基本上,Step1 和 Step2 迁移方法已步入正轨,但是,在 Step1 和 Step2 之后应用了第三种自动迁移。我删除了 Step2 迁移,实质上将其变成了自动迁移。当 update-database 运行时,它只应用 Step1,然后检查模型,自动创建 Step2 的内容并运行它们,欺骗其他开发人员的机器使模型和数据库重新保持一致。


public partial class ResetJobSites : DbMigration

    {

        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");

        }

    }

PM> update-database

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

总结一下:要在打开自动迁移时将一对一转换为一对多关系,您需要保留生产数据库(但愿意接受正在转换的表上的数据丢失)。

  • 创建显式迁移以解耦两个表(我通过注释掉类、Job 表上的 nav 属性、DbContext 中的 DbSet 以及构建项目所需的任何其他内容来实现此目的)。

  • 进行更改模型,将 nav 属性添加回 Job 表(ICollection nav 属性),将 DbSet 添加回 DbContext,然后让自动迁移运行。

  • 首先不要让自己陷入这种境地。


查看完整回答
反对 回复 2023-07-22
  • 1 回答
  • 0 关注
  • 124 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信