EF Code First Foreign Key Relationship

0

У меня есть следующая ситуация:

  • У меня есть несколько аккаунтов и несколько игр.
  • У каждого жанра есть создатель.
  • Каждая учетная запись может сидеть на столе (но не обязательно).

Мои классы моделей выглядят так:

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: "Невозможно определить главный конец связи между пространствами имен типов. GameTable" и "namespace.Account". Основной конец этой ассоциации должен быть явно сконфигурирован с использованием свободного API или аннотаций данных.

Однако, когда я комментирую одно из FK-отношений, все в порядке. Похоже, что между ними есть какой-то конфликт.

Результат, который я пытаюсь получить, - это один нулевой FK в Account под названием CurrentTableId и недействительный FK в GameTable называемый CreatorId.

Теги:
entity-framework
ef-code-first

2 ответа

0
Лучший ответ

С каждой стороны отношений FK вы можете (как обычно) обладать свойствами навигации. И когда есть несколько отношений FK, вы можете использовать InversePropertyAttribute, чтобы указать, какую FK представляет собой пара свойств навигации.

НАПРИМЕР

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
    свойства виртуальной навигации позволяют EF генерировать подтипы во время выполнения, реализация которых этих свойств фактически извлекает связанные объекты из базы данных по требованию. Это называется «Ленивая загрузка», если ваши свойства навигации не являются виртуальными, вы не можете получить «Ленивая загрузка», см. Msdn.microsoft.com/en-us/library/…
Показать ещё 1 комментарий
0

Это означает, что вы хотите создать собственную таблицу GameTable. Для этого вам нужно добавить свойство Collection в таблицу Account, например..

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

Надеюсь, что это решит вашу проблему.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню