2016-03-26 2 views
0

Я выборки фильм мета данные и 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, чтобы узнать, добавил ли я этот объект (человек), чтобы он не добавлял его повторно. Мысли?

+0

Она смотрит на меня, как вы держите один 'DbContext' глобально и повторно использовать его снова и снова. Это плохо. Вы должны «новый» в локальной области, выполнять небольшую работу с ним, «SaveChanges», затем «Dispose» и отбрасывать, в идеале используя оператор 'use' и сохраняя его в * локальной * области. Эти контексты не рассчитаны на долговечность. – spender

+0

С ленивой загрузкой этот код должен составлять десятки, возможно, больше запросов на каждую вставку. Ленивая загрузка и производительность не очень хорошо сочетаются. – spender

+0

это веб-сайт asp.net. У меня действительно есть живой контекст. но я не использую это в этом. новый контекст предоставляется для каждого вызова addorupdate. – Dmiller

ответ

0

Этот Movies.Where(My => My.ID == Movie.Id).FirstOrDefault() можно оптимизировать, позвонив по телефону Movies.Find(Movie.Id).

Находит объект с заданными значениями первичного ключа. Если в контексте существует сущность с указанными значениями первичного ключа, она немедленно возвращается без запроса в хранилище. https://msdn.microsoft.com/en-us/library/gg696418(v=vs.113).aspx

Я не вижу каких-либо оптимизаций для Add()

Смежные вопросы