Reputation: 25
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
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
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
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
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