【问题标题】:Composite Key in EFEF 中的复合键
【发布时间】:2015-08-28 08:36:27
【问题描述】:

我似乎无法理解 EF 如何处理复合键。当我尝试“添加迁移初始”时,以下代码返回“属性 'QuestionID' 不能用作实体 QuestionQuestionTypesModel 上的键属性,因为属性类型不是有效的键类型。只有标量类型、字符串和字节[] 是受支持的键类型。”

我还尝试设置注释而不是覆盖 OnModelCreating。我用 [Key, Column(Order = 0)]

谁能给我任何关于我做错了什么的线索?或者解释发生了什么以更好地理解手头的问题?

          public class QuestionModel
    {
        [Key]
        [HiddenInput(DisplayValue = false)]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public Guid ID { get; set; }

        [Required]
        [StringLength(250)]
        public string Question { get; set; }
   }


  public class QuestionTypeModel
    {
        [Key]
        [HiddenInput(DisplayValue = false)]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public Guid ID { get; set; }

        [Required]
        [StringLength(250)]
        public string TypeName { get; set; }
    }


  public class QuestionQuestionTypesModel
    {
        public virtual QuestionModel QuestionID {get;set;}
        public virtual QuestionTypeModel QuestionTypeID { get; set; }
    }

public class InnuendoContext : DbContext
    {

      public IContext() : base("DefaultConnection")
        {
        }

        public DbSet<QuestionTypeModel> QuestionTypes { get; set; }
        public DbSet<QuestionModel> Questions { get; set; }
        public DbSet<QuestionQuestionTypesModel> QuestionQuestionTypes { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            modelBuilder.Entity<QuestionQuestionTypesModel>().HasKey(a => new { a.QuestionID, a.QuestionTypeID });
        }
}

【问题讨论】:

  • CModel 中的AB 是什么?
  • 它们是表 A 和 B 的外键。
  • 此示例代码无法编译。 AB 没有定义,除非你说出它们的确切含义。请使用工作代码更新您的示例。如果没有,我会要求结束这个问题。
  • 我还是不明白为什么前面的代码不能编译。无论如何,我已经更新了代码。希望现在更清楚了。
  • 你没有包含A类和B类,只有AModel和BModel

标签: c# entity-framework


【解决方案1】:

您必须创建表所需的属性,这些属性也是系统的外键。通过设置这个结构:

public class QuestionQuestionTypesModel
{
    [Key, Column(Order = 1), ForeignKey("Question")]
    public Guid QuestionID { get; set; }
    [Key, Column(Order = 2), ForeignKey("QuestionType")]
    public Guid QuestionTypeID { get; set; }

    public virtual QuestionModel Question { get; set; }
    public virtual QuestionTypeModel QuestionType { get; set; }
}

你得到这个迁移:

public override void Up()
{
    CreateTable(
        "dbo.QuestionModel",
        c => new
        {
            ID = c.Guid(nullable: false, identity: true),
            Question = c.String(nullable: false, maxLength: 250),
        })
        .PrimaryKey(t => t.ID);

    CreateTable(
        "dbo.QuestionTypeModel",
        c => new
        {
            ID = c.Guid(nullable: false, identity: true),
            TypeName = c.String(nullable: false, maxLength: 250),
        })
        .PrimaryKey(t => t.ID);

    CreateTable(
        "dbo.QuestionQuestionTypesModel",
        c => new
            {
                QuestionID = c.Guid(nullable: false),
                QuestionTypeID = c.Guid(nullable: false),
            })
        .PrimaryKey(t => new { t.QuestionID, t.QuestionTypeID })
        .ForeignKey("dbo.QuestionModel", t => t.QuestionID, cascadeDelete: true)
        .ForeignKey("dbo.QuestionTypeModel", t => t.QuestionTypeID, cascadeDelete: true)
        .Index(t => t.QuestionID)
        .Index(t => t.QuestionTypeID);
}

更新 刚看到你的评论。如果您只有多对多关系并且不需要任何其他属性,则可以这样做:

public class QuestionModel
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public Guid ID { get; set; }

    [Required]
    [StringLength(250)]
    public string Question { get; set; }
    //One question has many QuestionTypes
    public virtual ICollection<QuestionTypeModel> QuestionTypes { get; set; }
}


public class QuestionTypeModel
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public Guid ID { get; set; }

    [Required]
    [StringLength(250)]
    public string TypeName { get; set; }
    //One QuestionType has many Questions
    public virtual ICollection<QuestionModel> Questions { get; set; }
}

这将产生相同的迁移,但会使您的数据层清晰。

【讨论】:

  • 这解释了很多。谢谢你。你的代码和解释很清楚谢谢!
【解决方案2】:
modelBuilder.Entity<QuestionQuestionTypesModel>().HasKey(a => new { a.QuestionID, a.QuestionTypeID });

QuestionID 和 QuestionTypeID 都是导航属性,因此不能用作主键。正如错误消息所暗示的那样:仅支持这些数据类型作为主键(可以转换为支持的数据库中的键列),不幸的是,QuestionModel 和 QuestionTypeModel 都不是这些。 添加 Guid 键值以匹配 QuestionModel 和 QuestionTypeModel 的键列。

【讨论】:

    猜你喜欢
    • 2019-06-23
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    相关资源
    最近更新 更多