2017-12-17 21 views
0

私は、次のような状況があります:私はいくつかのアカウントと少数gametablesを持ってEFコードファースト外部キー関係

  • を。
  • 各gametableにはクリエイターがいます。
  • 各アカウントはテーブルに座ることができます(ただし、必ずしもそうする必要はありません)。

私のモデルクラスは次のようになります。

public class GameTable 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id 
    { 
     get; 
     set; 
    } 

    [Required] 
    public string Name { get; set; } 

    [Required] 
    public string Description { get; set; } 

    public Guid CreatorId { get; set; } 

    [ForeignKey(nameof(CreatorId))] 
    public Account Creator { get; set; } 
} 

public class Account 
{ 
    public Account() 
    { 
     Elo = 1000; 
    } 

    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id { get; set; } 

    [Required] 
    [MaxLength(15)] 
    [MinLength(4)] 
    public string Name { get; set; } 

    [Required] 
    [MaxLength(32)] 
    [MinLength(32)] 
    public string PasswordHash { get; set; } 

    public int Elo { get; set; } 

    public bool IsAdmin { get; set; } 

    public Guid? CurrentTableId { get; set; } 

    [ForeignKey(nameof(CurrentTableId))] 
    public virtual GameTable CurrentTable { get; set; } 
} 

私のコンテキストでは、現在、このように探しています:

[Export(typeof(MyDbContext)), PartCreationPolicy(CreationPolicy.Shared)] 
[DbConfigurationType(typeof(MySqlEFConfiguration))] 
public class MyDbContext : DbContext 
{ 
    public MyDbContext() : base("DbContextCon") 
    { 
     Database.SetInitializer<PiksenDbContext>(new CreateDatabaseIfNotExists<PiksenDbContext>()); 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
    } 

    public virtual DbSet<Account> Accounts { get; set; } 
    public virtual DbSet<SecurityToken> SecurityTokens { get; set; } 
    public virtual DbSet<GameTable> GameTables { get; set; } 
} 

残念ながら、それは次のように設定し、外部キーの両方で動作しません。次のメッセージが、現時点では私のいくつかの頭痛を与えている:

のSystem.InvalidOperationException:namespace.GameTable 『と 『namespace.Account』「タイプの間の関連の主な 終わりを判断できません』を。この関連付けの主な終了点は、Fluent APIの関係または の注釈を使用して明示的に設定された である必要があります。

しかし、FK-Relationshipsのいずれかをコメントアウトすると、すべてが問題ありません。それらの2つの間に何らかの矛盾があるようです。

私が取得しようとしていた結果がAccountに1 NULL可能FKではCreatorIdと呼ばれるGameTableCurrentTableIdと呼ばれる非NULL可能FK。

+0

は、私の知る限り、データアノテーションを使用して利用できないなど)(WithRequiredPrincipleの承知している、あなたは流暢APIを使用して関係を設定する必要があります。 – DevilSuichiro

+0

@DevilSuichiro残念なことに、両方のguidがnullになり、両方のナビゲーションプロパティが仮想であっても、それでもエラーが表示されます。 – Jannik

+0

怠惰なローディング能力とカラムの必須/オプションパラメータは、プリンシパル/依存のアカウントでは関係ありません。 0..1から0へ..1リレーションシップ(またはその間のどこか)を使用する場合は、最初に挿入され、最後に削除されたリレーションシップのプリンシパルエンドを構成する必要があります。これがこのエラーの原因です。ナビゲーションプロパティの「状態」とは関係ありません。 – DevilSuichiro

答えて

0

FK関係の両側には、通常はナビゲーションプロパティが必要です。また、複数のFKリレーションシップがある場合は、InversePropertyAttributeを使用して、ナビゲーションプロパティのペアがどのFKを表すかを指定できます。

EG

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ef62test 
{ 
    class Program 
    { 

     public class GameTable 
     { 
      [Key] 
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
      public Guid Id 
      { 
       get; 
       set; 
      } 

      [Required] 
      public string Name { get; set; } 

      [Required] 
      public string Description { get; set; } 

      public Guid CreatorId { get; set; } 

      [ForeignKey(nameof(CreatorId))] 
      public Account Creator { get; set; } 

      [InverseProperty(nameof(Account.CurrentTable))] 
      public ICollection<Account> CurrentPlayers { get; } = new HashSet<Account>(); 
     } 

     public class Account 
     { 
      public Account() 
      { 
       Elo = 1000; 
      } 

      [Key] 
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
      public Guid Id { get; set; } 

      [Required] 
      [MaxLength(15)] 
      [MinLength(4)] 
      public string Name { get; set; } 

      [Required] 
      [MaxLength(32)] 
      [MinLength(32)] 
      public string PasswordHash { get; set; } 

      public int Elo { get; set; } 

      public bool IsAdmin { get; set; } 

      public Guid? CurrentTableId { get; set; } 

      [ForeignKey(nameof(CurrentTableId))] 
      public virtual GameTable CurrentTable { get; set; } 

      [InverseProperty(nameof(GameTable.Creator))] 
      public ICollection<GameTable> CreatedTables { get; } = new HashSet<GameTable>(); 
     } 


     public class MyDbContext : DbContext 
     { 
      public MyDbContext() : base("DbContextCon") 
      { 
       Database.SetInitializer<MyDbContext>(new CreateDatabaseIfNotExists<MyDbContext>()); 
      } 

      protected override void OnModelCreating(DbModelBuilder modelBuilder) 
      { 
       base.OnModelCreating(modelBuilder); 
      } 

      public virtual DbSet<Account> Accounts { get; set; } 
      //public virtual DbSet<SecurityToken> SecurityTokens { get; set; } 
      public virtual DbSet<GameTable> GameTables { get; set; } 
     } 
     static void Main(string[] args) 
     { 
      Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>()); 

      using (var db = new MyDbContext()) 
      { 
       db.Database.CreateIfNotExists(); 

      } 



      Console.WriteLine("Hit any key to exit."); 
      Console.ReadKey(); 
     } 
    } 
} 
+0

あなたの答えをありがとう。私は今それを得ると思います。私はあなたにもう1つ質問してもいいですか? - > "仮想"キーワード、私はそれを正しく使用しますか? nullableとnull-nullableとは関係がありますか? – Jannik

+1

仮想ナビゲーションプロパティを使用すると、EFはランタイムサブタイプを生成できます。ランタイムサブタイプは、これらのプロパティの実装によって、オンデマンドでデータベースから関連エンティティを実際にフェッチします。ナビゲーションプロパティが仮想でない場合、これは「レイジーロード」と呼ばれ、「レイジーロード」を取得することはできません。https://msdn.microsoft.com/en-us/library/jj574232%28v=vs.113%29を参照してください。 .aspx?f = 255&MSPPError = -2147217396 –

+0

ああ、私は実際にこれを知っていましたが、これを忘れてしまいました。ありがとうございました。 :) – Jannik

0

これは、自己参照GameTableテーブルを作成する継ぎ目です。あなたはアカウントテーブル

public virtual ICollection<GameTable> Children { get; set; } 

...のような全体のコードブロックにコレクションプロパティを追加する必要があります。これを行うために が

public class GameTable 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id 
    { 
     get; 
     set; 
    } 

    [Required] 
    public string Name { get; set; } 

    [Required] 
    public string Description { get; set; } 

    public Guid CreatorId { get; set; } 

    [ForeignKey(nameof(CreatorId))] 
    public Account Creator { get; set; } 
} 

    public class Account 
    { 
    public Account() 
    { 
     Elo = 1000; 
    } 

    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id { get; set; } 

    [Required] 
    [MaxLength(15)] 
    [MinLength(4)] 
    public string Name { get; set; } 

    [Required] 
    [MaxLength(32)] 
    [MinLength(32)] 
    public string PasswordHash { get; set; } 

    public int Elo { get; set; } 

    public bool IsAdmin { get; set; } 

    public Guid? CurrentTableId { get; set; } 

    [ForeignKey(nameof(CurrentTableId))] 
    public virtual GameTable CurrentTable { get; set; } 
    public virtual ICollection<GameTable> Children { get; set; } 
    } 

のように見えるが、それはあなたの問題を解決することを願っています。

関連する問題