使用C#MVC和Entity Framework v6.2.0
我有一个现有的模型,Caller
public class Caller
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
public string FirstName { get; set; }
}
我创建了一个新模型LanguageChoice
public class LanguageChoice
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
}
我想将此新LanguageChoice
添加到Caller
public class Caller
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
public string FirstName { get; set; }
public Guid LanguageChoice_Id { get; set; } // <----
[ForeignKey("LanguageChoice_Id")]
public LanguageChoice LanguageChoice { get; set; } // <----
}
我这样做是因为它在我的ViewModel中会是IEnumerable<SelectListItem>
。
在我的数据库中,我有Caller
条记录:
╔═════════════════════╦═══════════╗
║ Id ║ FirstName ║
╠═════════════════════╬═══════════╣
║ caller_guid_value_1 ║ Ryan ║
║ caller_guid_value_2 ║ John ║
╚═════════════════════╩═══════════╝
当我添加LanguageChoice
时,预期的结果将是:
╔═════════════════════╦═══════════╦═════════════════════════════╗
║ Id ║ FirstName ║ LanguageChoice_Id ║
╠═════════════════════╬═══════════╬═════════════════════════════╣
║ caller_guid_value_1 ║ Ryan ║ languageChoice_guid_value_1 ║
║ caller_guid_value_2 ║ John ║ languageChoice_guid_value_1 ║
╚═════════════════════╩═══════════╩═════════════════════════════╝
这是我的迁移:
public partial class AddCallerLanguageChoice : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.LanguageChoices",
c => new
{
Id = c.Guid(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 50),
})
.PrimaryKey(t => t.Id);
AddColumn("dbo.Callers", "LanguageChoice_Id", c => c.Guid(nullable: false));
CreateIndex("dbo.Callers", "LanguageChoice_Id");
AddForeignKey("dbo.Callers", "LanguageChoice_Id", "dbo.LanguageChoices", "Id", cascadeDelete: true);
}
public override void Down()
{
DropForeignKey("dbo.Callers", "LanguageChoice_Id", "dbo.LanguageChoices");
DropIndex("dbo.Callers", new[] { "LanguageChoice_Id" });
DropColumn("dbo.Callers", "LanguageChoice_Id");
DropTable("dbo.LanguageChoices");
}
}
这让我错误:
ALTER TABLE语句与FOREIGN KEY约束冲突&#34; FK_dbo.Callers_dbo.LanguageChoices_LanguageChoice_Id&#34;。冲突发生在数据库&#34; aspnet-My Web App-20171030040324&#34;,table&#34; dbo.LanguageChoices&#34;,column&#39; Id&#39;。
无论如何都要这样做,或者我应该继续前进,让LanguageChoice_Id
可以为空?
<小时/> 类似的问题来自4年前:Entity Framework The ALTER TABLE statement conflicted with the FOREIGN KEY constraint
int
ID为Ids,我使用Guid
,因此我无法提前猜测/假设Id值LanguageChoice_Id
可以为空的迁移,然后是一个更新记录的种子方法,然后是另一个使LanguageChoice_Id
不可为空的迁移,因为当推送它们时会破坏迁移到Azure,因为种子方法最后运行。 (参见Ari Roth对RicklsWright的评论&#39;回答)<小时/> 更新:
关注@henoc salinas&#39;更新的答案我来到这个有效的单一迁移文件。
Henoc的回答是接受的答案,这只是为了展示我最终得到的结果,不同之处在于我在此处插入了表值并使用非更新了Caller
的空值临时值:
public override void Up()
{
CreateTable(
"dbo.LanguageChoices",
c => new
{
Id = c.Guid(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 50),
})
.PrimaryKey(t => t.Id);
Sql(String.Format("INSERT INTO LanguageChoices VALUES ('{0}','{1}')", Guid.NewGuid(), "English"));
Sql(String.Format("INSERT INTO LanguageChoices VALUES ('{0}','{1}')", Guid.NewGuid(), "Other"));
Sql(String.Format("INSERT INTO LanguageChoices VALUES ('{0}','{1}')", Guid.NewGuid(), "Spanish"));
AddColumn("dbo.Callers", "LanguageChoice_Id", c => c.Guid(nullable: true));
Sql("UPDATE Callers Set LanguageChoice_Id = (SELECT Id FROM LanguageChoices WHERE Name = \'English\') WHERE LanguageChoice_Id IS NULL");
AlterColumn("dbo.Callers", "LanguageChoice_Id", c => c.Guid(nullable: false));
CreateIndex("dbo.Callers", "LanguageChoice_Id");
AddForeignKey("dbo.Callers", "LanguageChoice_Id", "dbo.LanguageChoices", "Id", cascadeDelete: true);
}
public override void Down()
{
DropForeignKey("dbo.Callers", "LanguageChoice_Id", "dbo.LanguageChoices");
DropIndex("dbo.Callers", new[] { "LanguageChoice_Id" });
DropColumn("dbo.Callers", "LanguageChoice_Id");
DropTable("dbo.LanguageChoices");
}
}
答案 0 :(得分:1)
生成此冲突是因为新表LanguageChoices在创建时没有元素,因此,外键找不到有效值,因为它不可为空,您可以尝试更改:
public Guid LanguageChoice_Id { get; set; }
到此:
public Guid? LanguageChoice_Id { get; set; }
然后再次生成迁移,您可以看到以下行:
AddColumn("dbo.Callers", "LanguageChoice_Id", c => c.Guid(nullable: false));
更改为:
AddColumn("dbo.Callers", "LanguageChoice_Id", c => c.Guid());
现在,您可以更新数据库,并将列更改为非null,添加有效值并再次更改该行,然后生成新的迁移:
public Guid? LanguageChoice_Id { get; set; }
为:
public Guid LanguageChoice_Id { get; set; }
评论后
在标记处插入sql代码:
public partial class AddCallerLanguageChoice : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.LanguageChoices",
c => new
{
Id = c.Guid(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 50),
})
.PrimaryKey(t => t.Id);
string TempKey = Guid.NewGuid ( ).ToString();
this.Sql ( String.Format ( "Insert into dbo.LanguageChoices values ({0},{1})", TempKey, "Initial" ) );
AddColumn("dbo.Callers", "LanguageChoice_Id", c => c.Guid(nullable: false));
Sql ( String.Format ( "Update dbo.Callers set LanguageChoice_Id='{0}' where LanguageChoice_Id is null", TempKey ) );
CreateIndex("dbo.Callers", "LanguageChoice_Id");
AddForeignKey("dbo.Callers", "LanguageChoice_Id", "dbo.LanguageChoices", "Id", cascadeDelete: true);
}
public override void Down()
{
DropForeignKey("dbo.Callers", "LanguageChoice_Id", "dbo.LanguageChoices");
DropIndex("dbo.Callers", new[] { "LanguageChoice_Id" });
DropColumn("dbo.Callers", "LanguageChoice_Id");
DropTable("dbo.LanguageChoices");
}
}