C# EF代码首先使用空查找表设置外键
我对与查找表和外键相关的EF代码首次迁移有问题。假设我的代码中有两个类:C# EF代码首先使用空查找表设置外键,c#,asp.net-mvc,entity-framework,ef-code-first,entity-framework-migrations,C#,Asp.net Mvc,Entity Framework,Ef Code First,Entity Framework Migrations,我对与查找表和外键相关的EF代码首次迁移有问题。假设我的代码中有两个类: public class Test { [Key] public long Id { get; set; } [Required] public string Title { get; set; } [Required, DisplayName("Test type")] public TestType TestType { get; set; } } public c
public class Test
{
[Key]
public long Id { get; set; }
[Required]
public string Title { get; set; }
[Required, DisplayName("Test type")]
public TestType TestType { get; set; }
}
public class TestType
{
public int Id { get; set; }
public string Name { get; set; }
}
TestType
是一个典型的查找表,我通常在Seed()方法中填充它们:
context.TestTypes.AddOrUpdate(
it => it.Name,
new TestType() { Name = "Drug" },
new TestType() { Name = "Educational" },
new TestType() { Name = "Other" }
);
当我使用关系创建表时,我得到以下迁移:
CreateTable(
"dbo.TestTypes",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(),
})
.PrimaryKey(t => t.Id);
AddColumn("dbo.Tests", "TestType_Id", c => c.Int(nullable: false));
CreateIndex("dbo.Tests", "TestType_Id");
AddForeignKey("dbo.Tests", "TestType_Id", "dbo.TestTypes", "Id", cascadeDelete: true);
现在,如果执行迁移,当然会出现错误,因为由于查找表仍然为空,并且创建的列没有默认值,因此无法使用外键
在开发中我可以通过简单地创建两个迁移来解决这个问题,第一个迁移用于创建查找表,第二个迁移用于设置外键。如果我单独运行它们,那么第一个之后的Seed方法将填充表,我可以调整列创建,从DB中提取值,在创建外键之前预先填充列,有点像这样:
AddColumn("dbo.Tests", "TestType_Id", c => c.Int(nullable: false));
Sql("UPDATE dbo.Tests SET TestType_Id = (SELECT TOP 1 Id FROM dbo.TestTypes)");
CreateIndex("dbo.Tests", "TestType_Id");
AddForeignKey("dbo.Tests", "TestType_Id", "dbo.TestTypes", "Id", cascadeDelete: true);
然后当我运行它时,一切正常
现在,在生产中我没有同样的奢侈,因为所有迁移都是在种子方法运行之前运行的,所以我总是会遇到同样的问题
我知道我也可以在生产数据库上以分步顺序运行迁移,但这并不能真正解决问题。。。假设我的一位同事更新了他的工作副本并运行了迁移,所有这些都将按顺序运行,他肯定会遇到错误。我不确定您数据库的当前状态,但我会这样定义您的模型
public class Test
{
[Key]
public long Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
[ForeignKey("TestType")]
public int TestTypeId { get; set; }
[DisplayName("Test type")]
public virtual TestType TestType { get; set; }
}
public class TestType
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
当表不存在时,将导致以下迁移。我总是发现显式描述外键效果更好
public override void Up()
{
CreateTable(
"dbo.Tests",
c => new
{
Id = c.Long(nullable: false, identity: true),
Title = c.String(nullable: false),
TestTypeId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.TestTypes", t => t.TestTypeId)
.Index(t => t.TestTypeId);
CreateTable(
"dbo.TestTypes",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(),
})
.PrimaryKey(t => t.Id);
}
然后,只要测试表为空,种子就可以正常工作?TestType是否也应该创建表?@Tallmaris您是否找到了解决此问题的好方法?不太可能。我基本上有一个选项,可以为新列设置nullable:true
,然后在将来进行调整(这并不理想),或者简单地将种子添加到迁移本身,因为它们彼此紧密相连。是的,问题是Test
表不是空的。。。是的,我使用相同的方法设置外键(我不喜欢下划线默认值),但上面只是示例代码。