2016-10-21 6 views
0

Ich versuche, Spiele in der Datenbank mit EntityFramework Code-First zu speichern.Entity Framework - Liste der Elemente lädt nicht

Es gibt Fragmente meiner Klassen:

/// <summary> 
/// Game class 
/// </summary> 
public class Game : ObservableObject 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int GameId { get; set; } 

    /// <summary> 
    /// List of teams 
    /// <see cref="Models.Teams"/> 
    /// </summary> 
    public Teams Teams 
    { 
     get 
     { 
      return teams; 
     } 
     set 
     { 
      teams = value; 
      OnPropertyChanged("Teams"); 
     } 
    } 
} 


/// <summary> 
/// Teams class 
/// </summary> 
public class Teams : ObservableObject, IEnumerable<Team> 
{ 
    public int GameId { get; set; } 

    public Game Game { get; set;} 

    List<Team> teamsList = new List<Team>(); 

    /// <summary> 
    /// List of teams 
    /// </summary> 
    public List<Team> TeamsList 
    { 
     get 
     { 
      return teamsList; 
     } 
     set 
     { 
      teamsList = value; 
      OnPropertyChanged("TeamsList"); 
     } 
    } 
} 

/// <summary> 
/// Team (group of players) 
/// </summary> 
public class Team : ObservableObject 
{ 


    #region Properties & fields 

    List<Player> players = null; 
    static int NumberOfTeams = 0; 

    /// <summary> 
    /// List of players in team 
    /// </summary> 
    public List<Player> Players 
    { 
     get 
     { 
      return players; 
     } 
     set 
     { 
      players = value; 

      OnPropertyChanged("NumberOfPlayers"); 
      OnPropertyChanged("IsEmpty"); 
      OnPropertyChanged("IsNotDefault"); 
      OnPropertyChanged("Players"); 
     } 
    } 
} 

/// <summary> 
///Defines player 
/// </summary> 
public class Player : Models.Person 
{ 

    /// <summary> 
    /// Identifies player in game. Also lets to recover player's statistics from last month 
    /// </summary> 
    public int PlayerId { get; set; } 
} 

Und das Entity Framework Teil:

public class GameContext : DbContext 
{ 
    public GameContext() : base("Db") 
    { 
     this.Configuration.LazyLoadingEnabled = false; 
     this.Configuration.ProxyCreationEnabled = true; 
    } 

    public DbSet<Models.Game> Games { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     //Configure domain classes using modelBuilder here 

     base.OnModelCreating(modelBuilder); 

     modelBuilder.Entity<Models.Devices>().HasKey(d => d.GameId); 
     modelBuilder.Entity<Models.Players>().HasKey(p => p.TeamId); 
     modelBuilder.Entity<Models.Teams>().HasKey(t => t.GameId); 
     modelBuilder.Entity<Models.Scenario>().HasKey(s => s.GameId); 

     modelBuilder.Entity<Models.Game>().HasOptional<Models.Teams>(g => g.Teams).WithRequired(t => t.Game); 
     modelBuilder.Entity<Models.Game>().HasOptional<Models.Scenario>(g => g.Scenario).WithRequired(s => s.Game); 
     modelBuilder.Entity<Models.Game>().HasOptional<Models.Devices>(g => g.Devices).WithRequired(d => d.Game); 

    } 
} 
public static class GameService 
{ 
    public static List<Models.Game> GetGames() 
    { 
     using (var gctx = new Contexts.GameContext()) 
     { 
      return gctx.Games.ToList(); 
     } 
    } 

    public static void InsertGame(Models.Game game) 
    { 
     using (var gctx = new Contexts.GameContext()) 
     { 
      gctx.Games.Add(game); 
      gctx.SaveChanges(); 
     } 
    } 
} 

Ich versuche alles so zu verwenden:

List<Models.Game> games = Services.GameService.GetGames().ToList(); 

     foreach(var game in games) 
     { 
      Console.WriteLine("Game " + game.GameId); 

      foreach (var team in game.Teams) 
      { 
       Console.Write("\t"); 
       Console.WriteLine("Team" + team.Number); 
       foreach(var player in team.Players) 
       { 
        Console.Write("\t\t"); 
        Console.WriteLine("Player" + player.PlayerId); 
       } 
      } 
     } 

Wenn Ich lasse diesen Code laufen, ich sehe meine Spiele, Mannschaften für diese Spiele, aber ich kann Spieler für jedes Team nicht erreichen. Meine Frage ist also: Was mache ich hier falsch?

+1

Wenn Sie das verzögerte Laden deaktiviert haben, müssen Sie zugehörige Entitäten explizit mit der Methode 'Include' laden (' using System.Data.Entity'). Weitere Informationen zur Verwendung von 'Include' finden Sie unter https://msdn.microsoft.com/en-us/data/jj574232(v=vs.113).aspx –

+1

Schön, dass es funktioniert!Der Grund, warum Lazy Loading hier nicht funktioniert, ist, dass Sie Ihren DbContext nach dem Abrufen Ihrer Daten in den Dienst stellen und eine ToList() ausführen. Jeder spätere Zugriff auf nicht in der Liste geladene Daten würde nicht funktionieren (der Kontext ist nicht mehr vorhanden, keine gültige Verbindung). Indem Sie Eager Loading mit expliziten Includes ausführen, lösen Sie das. Beachten Sie jedoch, dass Sie jedes Mal, wenn Sie einen Teil davon verwenden möchten, alle Daten in jedes Spiel laden müssen (das ist der Preis für eifriges Laden). Dies könnte in Zukunft zu Problemen führen. – Diana

+0

@Diana Ich weiß, dass es Probleme in den meisten Ausgaben verursacht, aber in meinem Fall ist es nicht so wichtig, weil ich nur wenige Spiele speichern muss. – Terrykk

Antwort

0

OK, ich habe mein Problem gelöst. Es gab wenige Gründe, die das Problem verursacht haben.

  1. Need verwenden Fügen Sie für Eager Loading. Methode sieht wie folgt aus:

    public static List<Models.Game> GetGames() 
    { 
        using (var gctx = new Contexts.DatabaseContext()) 
        { 
    
         return gctx.Games.Include(g => g.Teams).Include(g => g.Teams.TeamsList.Select(t => t.Players)).ToList(); 
        } 
    } 
    
  2. I verwendet Fluent API Beziehungen zu bestimmen (zwingende DatabaseContext.OnModelCreating):

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
    
        modelBuilder.Entity<Models.Game>().HasOptional(g => g.Teams).WithOptionalPrincipal(t => t.Game); // 1 -> 0..1 
        modelBuilder.Entity<Models.Game>().HasOptional(g => g.Devices).WithOptionalPrincipal(d => d.Game); // 1 -> 0..1 
        modelBuilder.Entity<Models.Game>().HasOptional(g => g.Scenario).WithOptionalPrincipal(s => s.Game); // 1-> 0..1 
    
        modelBuilder.Entity<Models.Teams>().HasMany(ts => ts.TeamsList).WithRequired(t => t.Teams); // 1 -> many 
        modelBuilder.Entity<Models.Team>().HasMany(t => t.Players).WithRequired(p => p.Team); // 1 -> many 
    
        base.OnModelCreating(modelBuilder); 
    
    
    } 
    
  3. Nur in Spielklasse Navigationseigenschaften nicht virtuell sind.

Danke für jede Hilfe in diesem Fall. Du bist wundervoll, Leute!

0

Entity Framework Lazy Lasten Objekte. Das bedeutet, dass nicht jedes Player-Objekt im Team-Objekt innerhalb des Game-Objekts geladen wird. Stattdessen gibt es einen Proxy zurück.

Versuchen Sie, eine IQueryable in der GetGames() Methode Rückkehr:

public static class GameService 
{ 
    public static IQuaryable<Models.Game> GetGames() 
    { 
     using (var gctx = new Contexts.GameContext()) 
     { 
      return gctx.Games.Select(....); 
     } 
    } 
} 
+0

Was sollte '.Select()' tun? – dotctor

+0

@dotctor Gibt alle als abfragbares Element vom Typ 'Game' zurück. So können Sie die gewünschten Eigenschaften abfragen. Wenn in Ihrem Beispiel @Terrykk zu einem späteren Zeitpunkt weitere Eigenschaften zum Player-Objekt hinzufügt, müssen Sie zurückgehen und sie auch explizit hinzufügen. Sobald sie abfragbar sind, lädt sie die von Ihnen benötigten Werte. –

+0

Ich habe das lazy loading in GameContext constuctor deaktiviert – Terrykk

1

Sie sollten die virtual Stichwort zu Ihrer Navigations Eigenschaften hinzufügen, das heißt, die Eigenschaften, die von EF automatisch gefüllt werden. Besonders wenn Sie Lazy Loading verwenden. Wenn eine Eigenschaft nicht als virtuell deklariert ist, kann EF sie nicht durch einen Proxy ersetzen. Daher funktioniert das verzögerte Laden nicht. Sie erhalten keine Ausnahmen, aber die Daten werden nicht geladen. Versuchen Sie das mal mit der Players Liste Eigenschaft:

public virtual List<Player> Players 

Auch Ihr Modell ein bisschen seltsam ist. Die Schlüssel in den Entitäten sollen Identifikatoren für das Unternehmen selbst, so etwas sein:

modelBuilder.Entity<Game>().HasKey(g => g.GameId); 
modelBuilder.Entity<Team>().HasKey(t => t.TeamId); 
modelBuilder.Entity<Player>().HasKey(p => p.PlayerId); 

Das ist, weil sie den Primärschlüssel für dieses Unternehmen sein werden. Sie verwenden sie stattdessen mehr wie Fremdschlüssel.

Verwandte Themen