Search code examples
c#linqentity-framework-coreauto-increment

Entity Framework data insertion with nested object having auto increment primary keys with one request


I am just curious to see if anyone knows of a way to insert nested objects that have auto increment keys without having to insert object one at a time.

For example, let's say I have the following tables in the database.

CREATE TABLE Analysis
(
    Analysis     bigint IDENTITY(1,1),
    AnalysisGuid uniqueidentifier NULL,
    Date         date(50)         NOT NULL,

    CONSTRAINT PK_Analysis PRIMARY KEY(AnalysisId)
);

CREATE TABLE Scenarios 
(
    ScenarioId   bigint IDENTITY(1,1),
    AnalysisId   bigint           NOT NULL,
    ScenarioGuid uniqueidentifier NULL,
    HVACNumber   int              NULL,

    CONSTRAINT FK_Scenarios_Analysis    
        FOREIGN KEY(Analysis) REFERENCES Analysis(AnalysisId)       
                ON DELETE CASCADE,
    CONSTRAINT PK_Scenarios PRIMARY KEY(ScenarioId)
);

Where Scenario to Analysis is a M:1 relationship. And there are some other nested objects with auto increment primary key underneath the Scenarios with M:1 relationship as well.

The object that comes through the API represents an nested Analysis Object at the top level. As speed is a concern for this application, is there a way to insert the data using Entity Framework Core without going through

Insert Analysis object --> SaveChanges() --> get the Analysis primary key --> go through the Scenarios list --> insert one by one --> SaveChanges() --> get the Scenario primary key --> ...

Any help would be appreciated. Thanks!


Solution

  • If your EF is properly/fully set up (nav properties between parent/child, keys declared to be db generated etc) you just add the child object to the parent's nav property, add the parent to the context set and save it..

    var p = new Parent();
    var c1 = new Child();
    var c2 = new Child();
    p.Children.Add(c1);
    p.Children.Add(c2); 
    
    context.Parents.Add(p);
    context.SaveChanges();
    

    After the save is done, the p.Id/c1.ParentId/c2.ParentId will be the parent ID calc'd by the db, and the c1.Id/c2.Id will also be their calc'd values.

    It'll work the other way round too (adding parent to children); the change tracker isn't fussy, so long as it can reach your changes somehow