I have found many questions here on SO and articles all over the internet but none really tackled my problem.
My model looks like this (I striped all non essential Properties):
Everyday or so “Play” gets updated (via a XML-file containing the information).
internal Play ParsePlayInfo(XDocument doc)
{
Play play = (from p in doc.Descendants("Play")
select new Play
{
Theatre = new Theatre()
{
//Properties
},
//Properties
LastUpdate = DateTime.Now
}).SingleOrDefault();
var actors = (from a in doc.XPathSelectElement(".//Play//Actors").Nodes()
select new Lecturer()
{
//Properties
});
var parts = (from p in doc.XPathSelectElement(".//Play//Parts").Nodes()
select new Part()
{
//Properties
}).ToList();
foreach (var item in parts)
{
play.Parts.Add(item);
}
var reviews = (from r in doc.XPathSelectElement(".//Play//Reviews").Nodes()
select new Review
{
//Properties
}).ToList();
for (int i = 0; i < reviews.Count(); i++)
{
PlayReviews pR = new PlayReviews()
{
Review = reviews[i],
Play = play,
//Properties
};
play.PlayReviews.Add(pR);
}
return play;
}
If I add this “play” via Add() every Childobject of Play will be inserted – regardless if some exist already. Since I need to update existing entries I have to do something about that. I guess the problem here is that I have no Id in the XML whatsoever.
As far as I can tell I have the following options:
- add/update the child entities in my
PlayRepositories Add-Method - restructure and rewrite
ParsePlayInfo() so that get all the
child entities first, add or update
them and then create a new Play.
The only problem I have here is that
I wanted ParsePlayInfo() to be
persistence ignorant, I could work
around this by - creating multiple
parse methods (eg ParseActors() )
and assign them to play in my
controller (I’m using ASP.net MVC)
after everything was parsed and added
Currently I am implementing option 1 – but it feels wrong.
What I want to do is update entities that are already in the database and insert new ones that aren’t.
Do I have to call SaveChanges() before I Attach/Add Play? There must be a (relatively) easy solution.
I’d appreciate it if someone could guide me in the right direction on this one.
Well, since there is no answer yet I’ll write one myself.
For those who are wondering, I got it to work – the code looks ugly as hell and I guess performance is even worse. But since there wont be many users and this method will only be called once a day at night anyway I am fine with it for now.
What did I do?
Well, I went with option 2 and 3.
(And on a side note, I just realized that I previously forgot to post this part of my code…)
As you can see, Save() gets called twice – and it gets worse when you consider whats going on in AddOrUpdate():
I can’t believe that this is “the right” way to do this.
It feels and looks just wrong. Maybe EF is to blame too, take
I haven’t tested this particular piece of code but from what I experienced is that I’ll end up with 10 new entries for SecondType and if I am not wrong 11 for FirstEntityType.
Why? Why isn’t there a mechanism in EF that says “Hey, wait a minute – those are the same!”
Am I that wrong thinking that EF should behave like if I was using the db directly? In my example, I added “first” so I could assume that whenever I use “first” it is referenced.
(I really hope my example works as described – don’t have the time nor the desire to test it)