c# - EF 代码优先外键关系

标签 c# mysql entity-framework ef-code-first

我有以下情况:

  • 我有几个帐户和一些游戏 table 。
  • 每个游戏 table 都有一个创建者。
  • 每个帐户都可以放在一个 table 上(但不是必须如此)。

我的模型类如下所示:

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: 'Unable to determine the principal end of an association between the types 'namespace.GameTable' and 'namespace.Account'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.'

但是,当我注释掉其中一个 FK-Relationships 时,一切都很好。两者之间似乎存在某种冲突。

我试图获得的结果是 Account 中名为 CurrentTableId 的可空 FK 和 GameTable 中名为 的不可空 FK >CreatorId.

最佳答案

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

关于c# - EF 代码优先外键关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47855131/

相关文章:

c# - ZedGraph 减少标签和轴标签之间的距离?

php - 从mysql数据库中检索记录

MySQL 去年同一天

c# - EFCore 保存具有关系 ID 的实体

c# - 如何使用变量名称以 _ 或 $ 开头的对象列表反序列化 JSON 响应

c# - 我可以在 AfterLabelEdit 期间将节点插入到 TreeView 中而不开始编辑它们吗?

c# - 如何从远程计算机的驱动器获取可用的 FreeSpace?

php - 查询 MySQL 的字谜

c# - Entity Framework 以编程方式将模型拆分为多个表

linq-to-sql - 使用 LINQ2SQL 或 Entity Framework 时,是否为大型数据库创建多个 .dbml/.edmx 文件?