Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将新表中的新外键添加到现有记录中_C#_Entity Framework_Tsql - Fatal编程技术网

C# 如何将新表中的新外键添加到现有记录中

C# 如何将新表中的新外键添加到现有记录中,c#,entity-framework,tsql,C#,Entity Framework,Tsql,使用C#MVC和实体框架v6.2.0 我有一个现有型号,Caller public class Caller { [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } [Required] public string FirstName { get; set; } } public class Caller { [Key, Data

使用C#MVC和实体框架v6.2.0

我有一个现有型号,
Caller

public class Caller
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    [Required]
    public string FirstName { get; set; }
}
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; } // <----
}
我创建了一个新模型,
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 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; } // <----
}
当我添加
语言选项
时,预期结果如下:

╔═════════════════════╦═══════════╦═════════════════════════════╗
║         身份证件║ 名字║      语言选择║
╠═════════════════════╬═══════════╬═════════════════════════════╣
║ 调用方\u guid\u值\u 1║ 赖安║ 语言选择\u guid\u值\u 1║
║ 调用方\u guid\u值\u 2║ 约翰║ 语言选择\u guid\u值\u 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语句与外键约束“FK_dbo.Callers_dbo.LanguageChoices_LanguageChoice_Id”冲突。冲突发生在数据库“aspnet My Web App-20171030040324”表“dbo.LanguageChoices”列“Id”中

有没有办法做到这一点,或者我应该继续允许
LanguageChoice\u Id
为空?


4年前的类似问题:

  • 4岁的时候,也许从那以后有些事情发生了变化
  • 他们使用的是Id的
    int
    值,我使用的是
    Guid
    ,所以我不能提前猜测/假设Id值
  • 我希望避免创建一个迁移,其中
    LanguageChoice\u Id
    可为空,然后是更新记录的种子方法,然后是另一个迁移,使
    LanguageChoice\u Id
    不可为空,因为将这两个迁移推到Azure时会中断,因为种子方法将最后运行。(见Ari Roth对RicklsWright回答的评论)

更新:

在“更新的答案”之后,我找到了一个有效的迁移文件

Henoc的答案是公认的答案,这只是为了说明我最终得到了什么,不同之处在于我在这里插入了表值,并使用非临时值更新了
调用者的空值:

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

生成此冲突的原因是新表LanguageChoices在创建时没有元素,因此,外键找不到有效值,因为它不可为null,您可以尝试更改:

 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());
现在,您可以更新数据库,并将列更改为NOTNULL,添加有效值并再次更改行,然后生成新迁移:

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

到目前为止,一切都没有改变(很不幸)。@IvanStoev好吧,这是一个令人沮丧的问题。这与我在帖子底部提到的问题不谋而合。我打算将这两个迁移同时推送到另一台服务器(我也会这样做)在EF尝试将空值更新为不可为空的字段之前,我将无法更改空值,因此会出现错误。您是否尝试在迁移和新表中创建列后插入sql代码以将值分配给新列?您可以在仅包含update语句的架构更改迁移之间的中间迁移:
Sql(“update…”)
根据您的建议,@BradleyUffner,我在它自己的迁移中有这样一句话:
string sqlStatement=“UPDATE Callers SET LanguageChoice\u Id=\'”+LanguageChoice.Id+“\'WHERE LanguageChoice\u Id为NULL”;Sql(sqlStatement)之后的迁移使
LanguageChoice\u Id
不可为空,这在一次执行一个迁移时有效,但不能同时执行所有迁移。我必须使用<代码> AptudioDbValue获得<代码> ID>代码>值,所以在迁移过程中,它错误地说AppultDbCurror已经更改。我编辑了我的ANSIS,请在评论之后再查看。