实体框架 - 当孩子具有复合主键时子项的父项 - 插入错误

时间:2014-05-10 13:47:13

标签: c# sql entity-framework ef-code-first

我有以下两个类:

public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Child> Children { get; set; }

    public Parent()
    {
        Children = new List<Child>();
    }
}

public class Child
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int? ParentId { get; set; }
    public virtual Parent Parent { get; set; }
}

然后是数据上下文中的Fluent设置:

modelBuilder.Entity<Child>()
                .HasKey(c => new { c.Id, c.ParentId })
                .HasOptional(c => c.Parent)
                .WithMany(p => p.Children)
                .WillCascadeOnDelete(true);

我执行此操作以便在我说parent.Children.Remove(aChild);时实际删除子对象,而不是仅将其设置为ParentId

问题是,我收到错误&#34;违反PRIMARY KEY约束&#39; PK_dbo.Child&#39;。无法在对象&#39; dbo.Child&#39;中插入重复的密钥。重复键值为(0,2)。&#34;当我创建一个有孩子的新父母,然后db.SaveChanges()

Parent p = new Parent { Name = "Quarterbacks" };
            p.Children.Add(new Child { Name = "Brady" });
            p.Children.Add(new Child { Name = "P. Manning" });
            p.Children.Add(new Child { Name = "Kaepernick" });
            p.Children.Add(new Child { Name = "Wilson" });
            p.Children.Add(new Child { Name = "Rodgers" });

            db.Parents.Add(p);

            db.SaveChanges();

我认为在插入时会自动生成整数主键。我该怎么办?我应该将键更改为字符串并在C#中创建GUID键才能使其生效吗?

1 个答案:

答案 0 :(得分:0)

我相信对于复合键,密钥的任何部分都没有标记为默认情况下的 ,即使不是整数键也是如此(简单就是这样) ,非复合键)。您可能必须明确地将Identity选项添加到Child实体的Id属性中:

modelBuilder.Entity<Child>()
    .Property(c => c.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

我有点担心你Child键的第二部分可以为空。也许EF确实允许这样做,但数据库不一定:我认为,使用SQL Server例如可以为空的关键部分是禁止的。也许,其他数据库可以解决这个问题。您显然的目标是识别关系(从父项中删除子项时将其从数据库中删除的那种),但是需要父项和父项之间的必需(非可选)关系。孩子,据我所知。