none
Performance problems with SQLite and Linq Selection RRS feed

  • Frage

  • I can not manage to select the data in a flat structure and detailed 
    information in a array of the same structure together in one select. 
    If I do it one after the other, the performance is pretty bad. 
    Perhaps someone can help me, here is an extract from the structures, 
    tables and the select statement.


    ============================================================
    --- Database
    ============================================================

    public class MovieDb
    {
    public string MovieGuid {get; set;}
    public string Title {get; set;}
    public string Plot {get; set;}
    public int Time {get; set;}
    public string Langu {get; set;}
    public int FSK {get; set;}
    ...
    }

    public class ActorDb
    {
    public string ActorGuid {get; set;}
    public string DisplayName {get; set;
    public string Firstname {get; set;
    public string Lastname {get; set;
    ...
    }

    public class ActorsInMovieDb
    {
    public string MovieGuid {get; set;}
    public string ActorGuid {get; set;}
    public string Role {get; set;}
    }

    public class ActorsInMovieDatabaseView
    {
    public string MovieGuid {get; set;}
    public string ActorGuid {get; set;}
    public string DisplayName {get; set;}
    public string Role {get; set;}
    }

    ============================================================
    --- View Classes
    ============================================================

    public class ActorItem
    {
    public string MovieGuid {get; set;}
    public string ActorGuid {get; set;}
    public string DisplayName {get; set;}
    public string Role {get; set;}
    }

    public class MovieItem
    {
    public string MovieGuid {get; set;}
    public string Title {get; set;}
    public string Plot {get; set;}
    public int Time {get; set;}
    public string Langu {get; set;}
    public int FSK {get; set;}
    ...
    public List<ActorItem> Actors {get; set;}
    }

    ============================================================
    --- Select
    ============================================================
    foreach (MovieDb record in database.MovieDb)
    {
       movieItem = new MediaItem(); 
       mediaItem = MappingMediaItem(record);
       // --- Now, select the actors
       movieItem.Actors = database.ActorsInMovieDatabaseView.AsNoTracking().Where(x => x.MovieGuid == record.MovieGuid).ToList();
                        //    Select(a => new
                        //    {
                        //        DisplayName = a.DisplayName,
                        //        Role = a.Role
                        //    }
                        //).ToList();
    }
    Donnerstag, 14. Januar 2021 16:06

Antworten

  • Hi,

    ich würde alle untergeordneten Elemente aller Hauptelemente auf einmal aus der Datenbank abfragen und die Zuweisung dann später in der Schleife vornehmen.

    List<Guid> movies = ( from n in database.MovieDb where ... select n ).Distinct().ToList();
    List<Guid> movieIds = ( from n in movies select n.MovieGuid ).Distinct().ToList();
    List<Actor> actors = ( from n in database.Actors select n ).AsNoTracking().Where( f => movieIds.Contains( f.MovieGuid ) ).ToList();
    
    foreach( MovieDb item in movies) {
        item.Actors = actors.Where( f => f.MovieGuid == item.MovieGuid );
    }

    Damit sparst Du dir alle Datenbankzugriffe bis auf zwei (einmal Movies, einmal Actors).

    Alternativ (wenn die Objekte auf Datenbankebene oder Codeebene passend aussehen und die Referenzen richtig gesetzt sind) kannst Du die untergeordneten Elemente auch gleich beim ersten Select mit auslesen.

    IQueryable<MovieDb> query = ( from n in database.MovieDb
        .Include( c => c.Actors )
        select n );


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport



    Donnerstag, 14. Januar 2021 17:07
    Moderator

Alle Antworten

  • Hi,

    ich würde alle untergeordneten Elemente aller Hauptelemente auf einmal aus der Datenbank abfragen und die Zuweisung dann später in der Schleife vornehmen.

    List<Guid> movies = ( from n in database.MovieDb where ... select n ).Distinct().ToList();
    List<Guid> movieIds = ( from n in movies select n.MovieGuid ).Distinct().ToList();
    List<Actor> actors = ( from n in database.Actors select n ).AsNoTracking().Where( f => movieIds.Contains( f.MovieGuid ) ).ToList();
    
    foreach( MovieDb item in movies) {
        item.Actors = actors.Where( f => f.MovieGuid == item.MovieGuid );
    }

    Damit sparst Du dir alle Datenbankzugriffe bis auf zwei (einmal Movies, einmal Actors).

    Alternativ (wenn die Objekte auf Datenbankebene oder Codeebene passend aussehen und die Referenzen richtig gesetzt sind) kannst Du die untergeordneten Elemente auch gleich beim ersten Select mit auslesen.

    IQueryable<MovieDb> query = ( from n in database.MovieDb
        .Include( c => c.Actors )
        select n );


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport



    Donnerstag, 14. Januar 2021 17:07
    Moderator
  • Hi,
    ergänzend zu Stefans Beitrag solltest du auch prüfen, ob jedes LinQ-Ergebnis zu persistieren ist (ToList). Möglicherweise ist das nicht erforderlich, spart Zeit und Speicherplatz.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Donnerstag, 14. Januar 2021 19:45
  • Vielen Dank für die Antwort, werde ich gleich ausprobieren
    Samstag, 16. Januar 2021 15:31