Jay Janarthanan
Jay Janarthanan

Reputation: 25

Entity Framework : Updating an existing child object with a new parent object

I am trying to do a data load using EF and stuck where I can't insert a new record when the child record is existing. Here is an example.

public class Position
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long Id { get; set; }
    public string PositionName { get; set; }
}

public class Application
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long Id { get; set; }
    public string ApplicationName { get; set; }
    public Position ApplicationPosotion { get; set; }
}

In the above example multiple Applications can belong to one Position. Assume we already have the Position record and if I make the following call, it will fail because Position with ID 5 is already in the database.

    public static void UseEntityFrameWorkOneFail()
    {
        using (var db = new DemoDbContext(@"Server=DESKTOP-HUJVOQ5\SQLEXPRESS;Database=Demo2;Trusted_Connection=True;"))
        {
            Application appOne = new Application
            {
                Id = 7,
                ApplicationName = "AppOne",
                ApplicationPosotion = new Position { Id = 5, PositionName = "ABC" }
            };

            db.Applications.Add(appOne);
            db.SaveChanges();

            appOne = db.Applications.Find(7);
            Console.WriteLine(appOne.ApplicationPosotion.PositionName);
        }
    }

Now I can pull that record and make a call like this and get it to work

     public static void UseEntityFrameWorkPass()
    {
        using (var db = new DemoDbContext(@"Server=DESKTOP-HUJVOQ5\SQLEXPRESS;Database=Demo2;Trusted_Connection=True;"))
        {
            Application appOne = new Application
            {
                Id = 8,
                ApplicationName = "AppOne",
                ApplicationPosotion = db.Positions.Find(5)
            };

            db.Applications.Add(appOne);
            db.SaveChanges();

            appOne = db.Applications.Find(8);
            Console.WriteLine(appOne.ApplicationPosotion.PositionName);
        }
    }

However I want to know if there is an easy way to do this. I am converting JSON to objects and saving for data loading purpose.

All I want is if the child record exists (in this case Position), then just update it with the new values. An Upsert

            Application appOne = new Application
            {
                Id = 7,
                ApplicationName = "AppOne",
                ApplicationPosotion = new Position { Id = 5, PositionName = "123" }
            };

            db.Applications.AddOrUpdate(appOne);
            db.SaveChanges();

The above example where I am using AddOrUpdate will do the Upsert for the parent object but not the child object. I want the child object also to be updated.

Thanks

Upvotes: 0

Views: 475

Answers (4)

Jay Janarthanan
Jay Janarthanan

Reputation: 25

Here is an example of 3 level deep

                Application appOne = new Application
            {
                Id = 7,
                ApplicationName = "AppOne",
                ApplicationPosition = new Position
                {
                    Id = 5,
                    PositionName = "123",
                    SalaryAmount = new Salary() { Id = 1, SalaryAmount = 200000 }
                }
            };

            db.Salarys.AddOrUpdate(appOne.ApplicationPosition.SalaryAmount);
            db.Positions.AddOrUpdate(appOne.ApplicationPosition);
            db.Applications.AddOrUpdate(appOne);
            db.SaveChanges();

            appOne = db.Applications.Find(7);
            Console.WriteLine(appOne.ApplicationPosition.SalaryAmount.SalaryAmount);

But I love to skip this step

          db.Salarys.AddOrUpdate(appOne.ApplicationPosition.SalaryAmount);
          db.Positions.AddOrUpdate(appOne.ApplicationPosition);

Because I do not want to set this up for every object.

Upvotes: 0

Jay Janarthanan
Jay Janarthanan

Reputation: 25

The above works. Here is my modified code.

                Application appOne = new Application
            {
                Id = 7,
                ApplicationName = "AppOne",
                ApplicationPosotion = new Position { Id = 5, PositionName = "123" }
            };

            db.Positions.AddOrUpdate(appOne.ApplicationPosotion);
            db.Applications.AddOrUpdate(appOne);
            db.SaveChanges();

            appOne = db.Applications.Find(7);
            Console.WriteLine(appOne.ApplicationPosotion.PositionName);

How ever is their a simple setting in EF that tells just do an Upsert ? Right now every object I have to break it down.

Upvotes: 0

Developer
Developer

Reputation: 6430

Is this what you are looking for? Do an update of ApplicationPosotion without hitting the database for Position of the given id (here 5)?

var position = new Position { Id = 5};
db.Positions.Attach(position);

            Application appOne = new Application
            {
                Id = 8,
                ApplicationName = "AppOne",
                ApplicationPosotion = position
            };

            db.Applications.Add(appOne);
            db.SaveChanges();

Upvotes: 0

Janaka Dissanayake
Janaka Dissanayake

Reputation: 547

var appPosotion = db.Positions.Any(o => o.Id== 5)) ?? new Position { Id = 5,   PositionName = "ABC" }

Application appOne = new Application
{
   Id = 8,
   ApplicationName = "AppOne",
   ApplicationPosotion = appPosotion  
};

Upvotes: 1

Related Questions