I Film Meta-Daten aus und API bin das Abrufen und das Hinzufügen von ihnen Datenbank Entity Framework mit dem folgenden CodeWie dieser Entity Framework Code optimieren
public static Movy AddOrUpdate(this TMDbLib.Objects.Movies.Movie Movie, TMDB Context = null)
{
//Check for duplicate items on every add() within foreach or for
if (Movie == null)
return null;
if (string.IsNullOrEmpty(Movie.Title))
return null;
//Managing IMDBID
var ImdbID = Movie.ImdbId;
if (!string.IsNullOrWhiteSpace(ImdbID))
ImdbID = ImdbID.Replace("/", "").Replace("tt", "");
var IMDBID = 0;
var TryParse = int.TryParse(ImdbID, out IMDBID);
if (TryParse == false || IMDBID == 0)
return null;
if (Context == null)
Context = Settings.EntityContexts.EntityContexts.TMDBContext;
Context.Configuration.LazyLoadingEnabled = true;
var Movy = Context.Movies.Where(My => My.ID == Movie.Id).FirstOrDefault();
if (Movy == null)
{
Movy = new Movy();
Movy.UrlTag = AspExtension.AspTools.StringHelper.Slugify(Movie.Title, MaxLength: 50);
Movy = Context.Movies.Add(Movy);
}
else
{
}
Movy.ImdbID = IMDBID;
Movy.ID = Movie.Id;
AspExtension.AspTools.StringHelper.MapObjects(Movie, Movy);
Movy.Adult = Movie.Adult ? 1 : 0;
if (Movie.AlternativeTitles != null && Movie.AlternativeTitles.Titles != null && Movie.AlternativeTitles.Titles.Count > 0)
{
if (Movy.AlternativeTitles == null)
{
Movy.AlternativeTitles = new List<Entities.TMDB.AlternativeTitle>();
}
foreach (var AlternativeTitle in Movie.AlternativeTitles.Titles)
{
var DBAlternativeTitle = Movy.AlternativeTitles.Where(My => My.Title == AlternativeTitle.Title && My.Iso_3166_1 == AlternativeTitle.Iso_3166_1).FirstOrDefault();
if (DBAlternativeTitle == null)
{
DBAlternativeTitle = new Entities.TMDB.AlternativeTitle();
Movy.AlternativeTitles.Add(DBAlternativeTitle);
}
DBAlternativeTitle.Title = AlternativeTitle.Title;
DBAlternativeTitle.Movy = Movy;
DBAlternativeTitle.MovieID = Movy.ID;
DBAlternativeTitle.Iso_3166_1 = AlternativeTitle.Iso_3166_1;
}
}
Movy.Budget = Movie.Budget;
if (Movie.Genres != null && Movie.Genres.Count > 0)
{
//This is a many to many relation ship, so first check if the genre is exsiting. if yes then use it.
// else just create new and populate it and add it to movie and add movie to genre and entity
//will create the records for u.
//Retrieve genres
var APIGenreIds = Movie.Genres.Select(My => My.Id).ToList();
var DBGenres = Context.Genres.Where(My => APIGenreIds.Contains(My.ID)).ToList();
if (Movy.Genres == null) Movy.Genres = new List<Entities.TMDB.Genre>();
foreach (var APIGenre in Movie.Genres)
{
var DBGenre = DBGenres.Where(My => My.ID == APIGenre.Id).FirstOrDefault();
if (DBGenre == null)
{
DBGenre = new Entities.TMDB.Genre();
}
DBGenre.ID = APIGenre.Id;
DBGenre.Name = APIGenre.Name;
DBGenre.Movies.Add(Movy);
Movy.Genres.Add(DBGenre);
}
}
//One to many relationship. Check and add.
if (Movie.Images != null && Movie.Images.Posters.Count > 0)
{
if (Movy.Images == null) Movy.Images = new List<Entities.TMDB.Image>();
foreach (var APIImage in Movie.Images.Posters)
{
var DBImage = Movy.Images.Where(My => My.FilePath == APIImage.FilePath).FirstOrDefault();
if (DBImage == null)
{
DBImage = new Entities.TMDB.Image();
Movy.Images.Add(DBImage);
}
DBImage.AspectRatio = (decimal)APIImage.AspectRatio;
DBImage.FilePath = APIImage.FilePath;
DBImage.Height = APIImage.Height;
DBImage.Iso_639_1 = APIImage.Iso_639_1;
DBImage.MovieID = Movy.ID;
DBImage.Movy = Movy;
DBImage.Type = "Poster";
DBImage.VoteAverage = (decimal)APIImage.VoteAverage;
DBImage.VoteCount = APIImage.VoteCount;
DBImage.Width = APIImage.Width;
}
}
if (Movie.Images != null && Movie.Images.Posters.Count > 0)
{
if (Movy.Images == null) Movy.Images = new List<Entities.TMDB.Image>();
foreach (var APIImage in Movie.Images.Posters)
{
var DBImage = Movy.Images.Where(My => My.FilePath == APIImage.FilePath).FirstOrDefault();
if (DBImage == null)
{
DBImage = new Entities.TMDB.Image();
Movy.Images.Add(DBImage);
}
DBImage.AspectRatio = (decimal)APIImage.AspectRatio;
DBImage.FilePath = APIImage.FilePath;
DBImage.Height = APIImage.Height;
DBImage.Iso_639_1 = APIImage.Iso_639_1;
DBImage.MovieID = Movy.ID;
DBImage.Movy = Movy;
DBImage.Type = "Poster";
DBImage.VoteAverage = (decimal)APIImage.VoteAverage;
DBImage.VoteCount = APIImage.VoteCount;
DBImage.Width = APIImage.Width;
}
}
Movy.HomePage = Movie.Homepage;
if (Movie.Keywords != null && Movie.Keywords.Keywords != null & Movie.Keywords.Keywords.Count > 0)
{
//Retrieve Keywords
var APIKeywordIds = Movie.Keywords.Keywords.Select(My => My.Id).ToList();
var DBKeywords = Context.Keywords.Where(My => APIKeywordIds.Contains(My.ID)).ToList();
if (Movy.Keywords == null) Movy.Keywords = new List<Entities.TMDB.Keyword>();
foreach (var APIKeyword in Movie.Keywords.Keywords)
{
var DBKeyword = DBKeywords.Where(My => My.ID == APIKeyword.Id).FirstOrDefault();
if (DBKeyword == null)
{
DBKeyword = new Entities.TMDB.Keyword();
}
DBKeyword.ID = APIKeyword.Id;
DBKeyword.Name = APIKeyword.Name;
DBKeyword.Movies.Add(Movy);
Movy.Keywords.Add(DBKeyword);
}
}
//Many to many, but this time joining table is consisting of a few other columns than
//just P Key and F Key
//So first check if person exist. if not add.
//Then check if cast object exists, if not add new
if (Movie.Credits != null && Movie.Credits.Cast != null && Movie.Credits.Cast.Count > 0)
{
//Retrieve Casts
var APICastIds = Movie.Credits.Cast.Select(My => My.Id).ToList(); //Person ids
var DBPersons = Context.Persons.Where(My => APICastIds.Contains(My.ID)).ToList();
var DBMovie_Casts = Context.Movie_Casts.Where(My => My.MovieID == Movy.ID).ToList();
if (Movy.Movie_Casts == null) Movy.Movie_Casts = new List<Entities.TMDB.Movie_Casts>();
foreach (var APICast in Movie.Credits.Cast)
{
var DBPerson = DBPersons.Where(My => My.ID == APICast.Id).FirstOrDefault();
if (DBPerson == null)
{
var LocalDBPerson = Context.Persons.Local.Where(My => My.ID == APICast.Id).FirstOrDefault();
if (LocalDBPerson == null)
{
DBPerson = new Entities.TMDB.Person();
DBPerson.ID = APICast.Id;
DBPerson = Context.Persons.Add(DBPerson);
}
else
{
DBPerson = LocalDBPerson;
}
}
DBPerson.Name = APICast.Name;
DBPerson.ProfilePath = APICast.ProfilePath;
var DBMovie_Cast = DBMovie_Casts.Where(My => My.MovieID == Movy.ID && My.CreditID == APICast.CreditId).FirstOrDefault();
if (DBMovie_Cast == null)
{
DBMovie_Cast = new Movie_Casts();
DBMovie_Cast.CastID = APICast.CastId;
DBMovie_Cast.CreditID = APICast.CreditId;
}
DBMovie_Cast.Cast_Order = APICast.Order;
DBMovie_Cast.Character = APICast.Character;
DBMovie_Cast.MovieID = Movy.ID;
DBMovie_Cast.Person = DBPerson;
DBMovie_Cast.PersonID = DBPerson.ID;
DBPerson.Movie_Casts.Add(DBMovie_Cast);
Movy.Movie_Casts.Add(DBMovie_Cast);
Context.SaveChanges();
}
}
if (Movie.Credits != null && Movie.Credits.Crew != null && Movie.Credits.Crew.Count > 0)
{
//Retrieve Crews
var APICrewIds = Movie.Credits.Crew.Select(My => My.Id).ToList();
var DBPersons = Context.Persons.Where(My => APICrewIds.Contains(My.ID)).ToList();
var DBMovie_Crews = Context.Movie_Crew.Where(My => My.MovieID == Movy.ID).ToList();
if (Movy.Movie_Crew == null) Movy.Movie_Crew = new List<Movie_Crew>();
foreach (var APICrew in Movie.Credits.Crew)
{
var DBPerson = DBPersons.Where(My => My.ID == APICrew.Id).FirstOrDefault();
if (DBPerson == null)
{
if (Context.Persons.Local.Where(My => My.ID == APICrew.Id).FirstOrDefault() == null)
{
DBPerson = new Entities.TMDB.Person();
DBPerson.ID = APICrew.Id;
Context.Persons.Add(DBPerson);
}
else
{
DBPerson = Context.Persons.Local.Where(My => My.ID == APICrew.Id).FirstOrDefault();
}
}
DBPerson.Name = APICrew.Name;
DBPerson.ProfilePath = APICrew.ProfilePath;
var DBMovie_Crew = DBMovie_Crews.Where(My => My.MovieID == Movy.ID && My.CreditID == APICrew.CreditId).FirstOrDefault();
if (DBMovie_Crew == null)
{
DBMovie_Crew = new Movie_Crew();
}
DBMovie_Crew.Department = APICrew.Department;
DBMovie_Crew.Job = APICrew.Job;
DBMovie_Crew.CreditID = APICrew.CreditId;
DBMovie_Crew.MovieID = Movy.ID;
DBMovie_Crew.Person = DBPerson;
DBMovie_Crew.PersonID = DBPerson.ID;
DBPerson.Movie_Crew.Add(DBMovie_Crew);
Movy.Movie_Crew.Add(DBMovie_Crew);
}
}
//Many to many, just like genres
if (Movie.ProductionCompanies != null && Movie.ProductionCompanies.Count > 0)
{
//Retrieve ProductionCompanies
var APIProductionCompanyIds = Movie.ProductionCompanies.Select(My => My.Id).ToList();
var DBProductionCompanies = Context.ProductionCompanies.Where(My => APIProductionCompanyIds.Contains(My.ID)).ToList();
if (Movy.ProductionCompanies == null) Movy.ProductionCompanies = new List<Entities.TMDB.ProductionCompany>();
foreach (var APIProductionCompany in Movie.ProductionCompanies)
{
var DBProductionCompany = DBProductionCompanies.Where(My => My.ID == APIProductionCompany.Id).FirstOrDefault();
if (DBProductionCompany == null)
{
DBProductionCompany = new Entities.TMDB.ProductionCompany();
}
DBProductionCompany.ID = APIProductionCompany.Id;
DBProductionCompany.Name = APIProductionCompany.Name;
DBProductionCompany.Movies.Add(Movy);
Movy.ProductionCompanies.Add(DBProductionCompany);
}
}
if (Movie.ProductionCountries != null && Movie.ProductionCountries.Count > 0)
{
//Retrieve ProductionCountries
var APIProductionCountryIds = Movie.ProductionCountries.Select(My => My.Iso_3166_1).ToList();
var DBProductionCountries = Context.ProductionCountries.Where(My => APIProductionCountryIds.Contains(My.ISo_3166_1)).ToList();
if (Movy.ProductionCountries == null) Movy.ProductionCountries = new List<Entities.TMDB.ProductionCountry>();
foreach (var APIProductionCountry in Movie.ProductionCountries)
{
var DBProductionCountry = DBProductionCountries.Where(My => My.ISo_3166_1 == APIProductionCountry.Iso_3166_1).FirstOrDefault();
if (DBProductionCountry == null)
{
DBProductionCountry = new Entities.TMDB.ProductionCountry();
}
DBProductionCountry.ISo_3166_1 = APIProductionCountry.Iso_3166_1;
DBProductionCountry.Name = APIProductionCountry.Name;
DBProductionCountry.Movies.Add(Movy);
Movy.ProductionCountries.Add(DBProductionCountry);
}
}
Movy.Popularity = (decimal)Movie.Popularity;
Movy.Revenue = Movie.Revenue;
if (Movie.SpokenLanguages != null && Movie.SpokenLanguages.Count > 0)
{
//Retrieve SpokenLanguages
var APISpokenLanguageIds = Movie.SpokenLanguages.Select(My => My.Iso_639_1).ToList();
var DBSpokenLanguages = Context.SpokenLanguages.Where(My => APISpokenLanguageIds.Contains(My.Iso_639_1)).ToList();
if (Movy.SpokenLanguages == null) Movy.SpokenLanguages = new List<Entities.TMDB.SpokenLanguage>();
foreach (var APISpokenLanguage in Movie.SpokenLanguages)
{
var DBSpokenLanguage = DBSpokenLanguages.Where(My => My.Iso_639_1 == APISpokenLanguage.Iso_639_1).FirstOrDefault();
if (DBSpokenLanguage == null)
{
DBSpokenLanguage = new Entities.TMDB.SpokenLanguage();
}
DBSpokenLanguage.Iso_639_1 = APISpokenLanguage.Iso_639_1;
DBSpokenLanguage.Name = APISpokenLanguage.Name;
DBSpokenLanguage.Movies.Add(Movy);
Movy.SpokenLanguages.Add(DBSpokenLanguage);
}
}
Movy.VoteAverage = (decimal) Movie.VoteAverage;
Movy.VoteCount = Movie.VoteCount;
if (Movie.Videos != null && Movie.Videos.Results != null && Movie.Videos.Results.Count > 0)
{
if (Movy.Videos == null)
{
Movy.Videos = new List<Entities.TMDB.Video>();
}
foreach (var Video in Movie.Videos.Results)
{
var DBVideo = Movy.Videos.Where(My => My.ID == Video.Id).FirstOrDefault();
if (DBVideo == null)
{
DBVideo = new Entities.TMDB.Video();
Movy.Videos.Add(DBVideo);
}
DBVideo.ID = Video.Id;
DBVideo.Iso_639_1 = Video.Iso_639_1;
DBVideo.Name = Video.Name;
DBVideo.Site = Video.Site;
DBVideo.Type = Video.Type;
DBVideo.VideoKey = Video.Key;
DBVideo.Movy = Movy;
DBVideo.MovieID = Movy.ID;
}
}
//Similar Items
if (Movie.Similar != null && Movie.Similar.Results != null && Movie.Similar.Results.Count > 0)
{
foreach (var SimilarItem in Movie.Similar.Results)
{
DB.DBUtilities.Set.AddSimilarMoviesToContext(Movie.Id, SimilarItem.Id);
}
}
Movy.LastUpdated = DateTime.Now;
Context.SaveChanges();
return Movy;
}
Dieser Code wobei dies bis zu 20% CPU verwenden, wenn gefordert ein Film. Ich verwende einen Kontext für eine Einfügung. Add() und DBSet.Local.Where (..) Methoden sind hier am teuersten. Wie kann ich den Code optimieren, um die CPU zu reduzieren?
Update: Auf Code-Profilierung fand ich DBSet.Local.Where (..) ist, wo die CPU auffrisst. Mein Grund, DBSet.Local.Where zu nennen, ist herauszufinden, ob ich dieses Objekt (Person) bereits hinzugefügt habe, damit ich es nicht wieder hinzufüge. Gedanken?
Es sieht für mich wie Sie ein einzelnes 'DbContext' global Hand halten und es immer wieder wiederverwendet. Das ist schlecht. Sie sollten "neu" im lokalen Bereich arbeiten, kleine Mengen an Arbeit damit erledigen, "Speichern", dann "Entsorgen" und verwerfen, idealerweise mit einer 'using'-Anweisung und im * lokalen * Geltungsbereich behaltend. Diese Kontexte sind nicht dafür ausgelegt, langlebig zu sein. – spender
Mit Lazy Loading, dieser Code muss Dutzende, möglicherweise mehr Abfragen pro einfügen. Lazy Loading und Leistung passen nicht gut zusammen. – spender
Dies ist eine asp.net-Website. Ich habe einen langen Live-Kontext. aber ich benutze das nicht darin. Für jeden Film addorupdate-Aufruf wird ein neuer Kontext bereitgestellt. – Dmiller