I retrieve movie data from an external API. In a first phase I will scrape each movie and insert it into my own database. In a second phase I will periodically update my database by using the API's "Changes" API which I can query to see what movies have had their information changed.
My ORM layer is Entity-Framework. The Movie class looks like this:
class Movie
{
public virtual ICollection<Language> SpokenLanguages { get; set; }
public virtual ICollection<Genre> Genres { get; set; }
public virtual ICollection<Keyword> Keywords { get; set; }
}
The problem arises when I have a movie that needs to be updated: my database will think of the object being tracked and the new one that I receive from the update API call as different objects, disregarding .Equals()
.
This causes a problem because when I now try to update the database with the updated movie, it will insert it instead of updating the existing Movie.
I had this issue before with the languages and my solution was to search for the attached language objects, detach them from the context, move their PK to the updated object and attach that to the context. When SaveChanges()
is now executed, it will essentially replace it.
This is a rather smelly approach because if I continue this approach to my Movie
object, it means I'll have to detach the movie, the languages, the genres and the keywords, look up each one in the database, transfer their IDs and insert the new objects.
Is there a way to do this more elegantly? Ideally I just want to pass in the updated movie to the context and have that select the correct movie to update based on the Equals()
method, update all its fields and for each complex object: use the existing record again based on its own Equals()
method and insert if it doesn't exist yet.
I can skip the detaching/attaching by providing .Update()
methods on each complex object which I can use in combination of retrieving all the attached objects but this will still require me to retrieve every single existing object to then update it.
id
and the movies from the external API are matched to the local ones using the fieldtmdbid
. I can't retrieve all entities that need to be updated in one call because it's about movies, genres, languages, keywords, etc. Each of these have a PK and might already exist in the database.