0

I have two simple DB Tables:

Persons (id, name, house)

Houses (id, street, city)

The 'house' column of the Persons table is the foreign key to specify in which house a person lives. Easy example. I created a model from the Database and now I am trying to learn how to work with the EF. I am for instance trying to attach a disconnected entity to an existing context:

    House dh = new House() { city = "Seattle", street = "St Road 1" };
    dh.Persons = new List<Person>();
    dh.Persons.Add(new Person { namen = "Andrew" });
    dh.Persons.Add(new Person { namen = "Thorsten" });

    YardEntities cx = new YardEntities();
    cx.Houses.Attach(dh);

The last line throws an Exception I do not understand:

Additional information: Attaching an entity of type 'DataAccessLayer.Person' failed because another entity of the same type already has the same primary key value.

Why is that? Andy ideas? The primary key 'id' has an auto increment and is the primary key of my tables.

Edit:

Code of my two entity classes:

public partial class Person
{
    public int id { get; set; }
    public string namen { get; set; }
    public int house { get; set; }

    public virtual House House1 { get; set; }
}

public partial class House
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public House()
    {
        this.Persons = new HashSet<Person>();
    }

    public int id { get; set; }
    public string street { get; set; }
    public string city { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Person> Persons { get; set; }
}
David
  • 1,275
  • 2
  • 17
  • 27
  • Share the code of the classes `Person` and `House`. It seems that `Id` is not set to `autoincrement`. When you don't define it in the instanciation, the Id property take the default value of ite type (0 for `int`). Here, your 2 persons have the same `Id`. – ADreNaLiNe-DJ Jul 07 '16 at 08:33
  • I only set the autoincrement in the database. The code for my two entities is generated by the model generator: – David Jul 07 '16 at 08:40
  • So the column is `IDENTITY` on the 2 tables ? – ADreNaLiNe-DJ Jul 07 '16 at 08:41
  • Yes my tables both have the IDENTITY flag in id. But in the generated code I cannot see anything regarding this. – David Jul 07 '16 at 08:43
  • You might have a look at my answer on [ASP.NET MVC - Attaching an entity of type 'MODELNAME' failed because another entity of the same type already has the same primary key value](http://stackoverflow.com/questions/23201907/asp-net-mvc-attaching-an-entity-of-type-modelname-failed-because-another-ent/39557606#39557606). – Murat Yıldız Sep 18 '16 at 12:39

1 Answers1

0

In your situation, I suggest you to test the second solution for DatabaseFirst context.

It seems to be a problem whit the definiton of the Primary Key and Entity Framework.

To have this problem of duplicate key, it's because it is no defined as identity (autoincrement) => your code shows that you don't define the Id when you add new Person or a House.

For DatabaseFirst context, you have the choice of solutions:

  • You modify your table to make the Id column Identity.
  • You define the Id property like this:

    House dh = new House() { Id = 1, city = "Seattle", street = "St Road 1" };
    dh.Persons.Add(new Person { Id = 1, namen = "Andrew" });
    dh.Persons.Add(new Person { Id = 2, namen = "Thorsten" });
    

For CodeFirst context, you have this 2 solutions:

  • CodeFluent solution:

    modelBuilder
        .Entity<Person>()
        .Property(f => f.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    
  • DataAttribute solution:

    public class Person
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public long Id{ get; set; }
    
        // ...
    }
    
ADreNaLiNe-DJ
  • 4,787
  • 3
  • 26
  • 35
  • But if I use "add" instead of "attach" everything works fine. I thought, that the only difference between attach and add is that the state is not set to "added" automatically. But I cannot even set the state if I am not allowed to attach my disconnected type first. – David Jul 07 '16 at 08:49
  • And how should I always know the next key? Your code shows, that I should specify the ID with 1, but it might be another one the next time. – David Jul 07 '16 at 08:49
  • You can't directly, except making a query tatht takes the `Max` id from the table. I think you should always use `Add` to ensure your objects have the correct state flag. – ADreNaLiNe-DJ Jul 07 '16 at 08:53
  • Yes, that would be my solution too. But then I absolutely do not understand the purpose of "Attach". – David Jul 07 '16 at 08:55