Я выборки фильм мета данные и API и добавление их в базу данных, используя структуру сущностей, используя следующий кодКак оптимизировать этот рамочный объект кода
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;
}
Этот код это взятие ДО 20% CPU при вызове один фильм. Я использую один контекст для одной вставки. Add() и DBSet.Local.Where (..) методы являются самыми дорогими здесь. Как я могу оптимизировать код для снижения производительности процессора.
Обновление: при профилировании кода я нашел DBSet.Local.Where (..) где находится процессор. Моя причина для вызова DBSet.Local.Where, чтобы узнать, добавил ли я этот объект (человек), чтобы он не добавлял его повторно. Мысли?
Она смотрит на меня, как вы держите один 'DbContext' глобально и повторно использовать его снова и снова. Это плохо. Вы должны «новый» в локальной области, выполнять небольшую работу с ним, «SaveChanges», затем «Dispose» и отбрасывать, в идеале используя оператор 'use' и сохраняя его в * локальной * области. Эти контексты не рассчитаны на долговечность. – spender
С ленивой загрузкой этот код должен составлять десятки, возможно, больше запросов на каждую вставку. Ленивая загрузка и производительность не очень хорошо сочетаются. – spender
это веб-сайт asp.net. У меня действительно есть живой контекст. но я не использую это в этом. новый контекст предоставляется для каждого вызова addorupdate. – Dmiller