简体   繁体   中英

Entity Framework - Parent to Children When Child Has Composite Primary Key - Insert Error

I have the following two classes:

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

And then the Fluent setting in the data context:

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

I'm doing this so that I actually delete the child object when I say parent.Children.Remove(aChild); , not just set its ParentId null.

The problem is, I'm getting the error "Violation of PRIMARY KEY constraint 'PK_dbo.Child'. Cannot insert duplicate key in object 'dbo.Child'. The duplicate key value is (0, 2)." when I create a fresh parent with children, and then 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();

I thought integer primary keys are auto-generated on insertion. What should I do? Should I change the keys to strings and create GUID keys in C# for this to work?

I believe that for composite keys no part of the key is marked as an identity by default , even not for integer keys (which would be the case for a simple, non-composite key). You probably must add the Identity option explicitly to the Child entity's Id property:

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

I'm a bit worried that your second part of the Child 's key is nullable. Perhaps EF does allow that, but the database not necessarily: I think, with SQL Server for example nullable key parts are forbidden. Maybe, other databases can deal with that. You're apparently aiming for an identifying relationship (the one that deletes the child from the database when it is removed from the parent) which however needs a required (not an optional) relationship between parent and child, as far as I know.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM