How to save an entity with a child entity which already exists in EF core?

ef core save related entities
how do i stop entity framework from trying to save/insert child objects
entity framework save object with foreign key
ef core add child entity
entity framework core save object with foreign key
ef core update related entities
entity framework add new record with existing foreign key
entity framework update related entities

I ran into a very weird problem I've never seen before. I'm using .net CORE 3.0 + EF. I have two database models, which are

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Dog Dog { get; set; }
}

and

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

So, let's say I already have a Dog record in my database with id=1 and Name = "Bimbo". Now, I want to add a person with an existing dog:

var p = new Person
{
    Name = "Peter",
    Dog = new Dog
    {
        Id = 1
    };
};

_dbContext.Persons.Add(p);

Then I get

Cannot insert explicit value for identity column in table 'Dogs' when IDENTITY_INSERT is set to OFF

I understand that EF tries to insert a dog as a new record, while I need it to bind my new Person record with an existing Dog record.

I found this solution which suggests setting a foreign key explicitly. Is there another way to do it? Or is it the right way to handle such situation? EF Core insert explicit value for identity column

You have three options to do that

  1. Use the Foreign-Key property

    using ( var db = new MyDbContext(options) )
    {
        var person = new Person
        {
            Name = "Paul",
            DogId = 1
        };
    
        db.Persons.Add(person);
        await db.SaveChangesAsync();
    }
    
  2. Load the dog instance from the context and use that instance

    using ( var db = new MyDbContext(options) )
    {
        var dog = db.Dogs.Find(1);
    
        var person = new Person
        {
            Name = "Paul",
            Dog = dog
        };
    
        db.Persons.Add(person);
        await db.SaveChangesAsync();
    }
    
  3. Create a dog instance with explicit ID and attach that to the context

    using ( var db = new MyDbContext(options) )
    {
        var dog = new Dog
        {
            Id = 1
        };
    
        db.Attach(dog);
    
        var person = new Person
        {
            Name = "Paul",
            Dog = dog
        };
    
        db.Persons.Add(person);
        await db.SaveChangesAsync();
    }
    

See working example on .net fiddle

Saving Related Data, If you create several new related entities, adding one of them to the context new entity from the navigation property of an entity that is already tracked a cascade delete behavior is configured and the child/dependent entity� As far as I know EF can save child entities only if the parent object was retrieved with the same Context that is trying to save it. That is attaching an object that was retrieved by one context to another context, will allow you to save changes to parent objects but not children.

you can explicitly add the Foreign key to person

   public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int DogId {get;set;}
        public Dog Dog { get; set; }
    }

then you can the add the dog as reference without load it to context

var p = new Person
{
    Name = "Peter",
    DogId = 1
};

_dbContext.Persons.Add(p)

;

How do I stop Entity Framework from trying to save/insert child , However, these definitions already exist and I don't want to create duplicates in the database. I only use the EF object to do a lookup and� If you are using EF core 2 for SQL Server, and you remove an entity from a child collection in a Parent,, EF sets the state of the deleted entity to be Modified, but it does delete the entity from the DB when you call SaveChanges. I am hooking into the SaveChanges event to do the check.

When you add the Person object to the context, EF sets its state to Added, as well as any object it references that has their primary key set (as stated here). This is why EF tries to insert a new Dog object into the database with a new id, while the exception states that the ids for the Dogs table are generated by the database.

To work around this you can manually set the state of the new Dog object to Unchanged which will prevent EF from inserting a new record to the database.:

_dbContext.Entry(person.Dog).State = EntityState.Unchanged

Better solutions will be to add a DogId property to the Person object and set it instead of creating a new Dog instance or to load the Dog object from the database and set it to the Dog property of the Person object (as suggested in the comments).

Attaching an entity with a mix of existing and new entities in its graph , kall2sollies changed the title EF tries to insert existing entities then all entities discovered as children of that entity will also be marked as Added. Could you please tell us if that change is already milestoned in a future release ? (https:// docs.microsoft.com/en-us/ef/core/saving/disconnected-entities)� In EF Core 2.0, navigations to owned entity types cannot be declared in derived entity types unless the owned entities are explicitly mapped to a separate table from the owner hierarchy. This limitation has been removed in EF Core 2.1; In EF Core 2.0 and 2.1 only reference navigations to owned types were supported.

Adding New related entity tries to insert primary key value causing , I'm create a few related entities and attempting to save them. The entities are new , but for some reason EF is attempting to insert the dotnet / efcore (attempting to insert an entity with Key '0', which already exists in the DB. Here, you have to make list of itemIds first because EF cannot inline list of items in a query and will do evaluation on client otherwise. That means EF is fetching whole table. Same is true for your GetitemsAsync method. It also queries whole table. Consider creating itemIds locally in that method too.

Managing One To Many Relationships With Entity Framework Core , Entity Framework Core offers a number of approaches to the creation and modification telling the context that the entities with the specified keys already exist. An entity can be in one of five states as defined by the EntityState enumeration. These states are: Added: the entity is being tracked by the context but does not yet exist in the database; Unchanged: the entity is being tracked by the context and exists in the database, and its property values have not changed from the values in the database

bulk-insert | Entity Framework bulk-insert, Insert only if the entity not already exists; Insert with related child entities (Include Graph); Insert with future action; Insert without returning identity value; More� Before EF Core 3.0 the property named exactly the same as the principal key property was also matched as the foreign key No foreign key property While it is recommended to have a foreign key property defined in the dependent entity class, it is not required.

Comments
  • Load the existing dog instance from the context and assign that instance to the person Dog property, add that person to the context and save.
  • Yeah, I understand how to handle it. But this looks like a workaround for me. Wouldn't it be more logical if EF tried to find an existing dog with provided id?
  • EF does that only when you have a foreign key on person and when you set it explicitly. Having explicitly defined foreign keys is a good practice for EF.
  • Thank you for the answer!