2016-10-21 12 views
0

私はEntityFramework Code-Firstでデータベースにゲームを保存しようとしています。Entity Framework - アイテムのリストがロードされていません

私のクラスの断片があります

/// <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; } 
} 

とエンティティフレームワークの一部:

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(); 
     } 
    } 
} 

私はこのようにそれをすべてを使用しようとしている:

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); 
       } 
      } 
     } 

とき私はこのコードを実行して私のゲーム、そのゲームのチームを見るが、私は各チームのプレーヤーには届かない。だから私の質問は:私はここで間違っているの?

+1

遅延読み込みを無効にした場合、関連エンティティを 'Include'メソッド(' using System.Data.Entity')で明示的に読み込む必要があります。 'Include'の使用に関する詳細はhttps://msdn.microsoft.com/en-us/data/jj574232(v=vs.113).aspx –

+1

をご覧ください。Lazy Loadingがここで動作しないのは、データを取得してToList()を実行した後にDbContextをサービスに配置することです。したがって、あなたのリストに熱心にロードされていないデータへの後のアクセスは機能しません(コンテキストはもう存在せず、有効な接続はありません)。明示的なインクルードでEager Loadingを行うことで、それを解決できます。ただし、すべてのデータをすべてのゲームで使用するたびに、すべてのデータをロードする必要があることに注意してください(これは熱心なローディングの価格です)。将来的に規模の問題を引き起こす可能性があります。 – Diana

+0

@ダイアナ私はそれがほとんどの問題で問題を引き起こすことは知っていますが、私の場合はそれほど重要ではありません。 – Terrykk

答えて

0

問題を解決しました。問題を引き起こした理由はほとんどありませんでした。

  1. を使用する必要が積極的なロードのためのを含めます。この方法は、以下のようになります。

    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. 私は(DatabaseContext.OnModelCreatingをオーバーライド)の関係を決定するために流暢APIを使用:唯一のゲームクラスのナビゲーションプロパティで

    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. は、仮想ではありません。

この場合はお手数ですが、あなたは素晴らしいよ、みんな!

0

Entity Frameworkはオブジェクトを遅延ロードします。 つまり、Gameオブジェクト内のTeamオブジェクトに各Playerオブジェクトを実際にロードするわけではありません。むしろ、プロキシを返します。

GetGames()方法でのIQueryableを返す試してみてください。

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

'.Select()'は何をすべきですか? – dotctor

+0

@dotctorこれは 'Game'型のクエリ可能なアイテムとしてすべてを返します。したがって、必要なプロパティをクエリできます。 あなたの例では、後の段階で@TerrykkがPlayerオブジェクトにさらに多くのプロパティを追加すると、戻って明示的にそれらを追加する必要があります。クエリ可能な場所では、クエリを実行するとすぐに、必要な値がロードされます。 –

+0

GameContextコンストラクタで遅延ロードをオフにしました – Terrykk

1

あなたのナビゲーションプロパティ、つまり、自動的にEFによって満たされるプロパティにvirtualキーワードを追加する必要があります。特に、遅延ロードを使用している場合。プロパティが仮想として宣言されていない場合、EFはそれをプロキシで置き換えることができないため、遅延ロードは機能しません。例外は発生しませんが、データはロードされません。 Playersリストプロパティでのことを試してみてください:

public virtual List<Player> Players 

また、あなたのモデルは少し奇妙です。彼らはそれらのエンティティの主キーになるためである

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

:エンティティのキ​​ーは、エンティティ自体の識別子、このようなものであると考えられています。あなたは代わりにそれらを外国キーのように使用しています。

関連する問題