为了账号安全,请及时绑定邮箱和手机立即绑定

与实体框架一对一关系的抽象类

与实体框架一对一关系的抽象类

C#
繁华开满天机 2023-08-13 09:41:33
我一直在尝试使用实体框架来创建这种关系。基本上我有 1 个对象,其中有一个Result. 该Result对象是抽象的,因为它必须是继承自 的 3 个类之一Result,即Approved、Rejected或Modified:我正在尝试使用实体框架创建表结构。最初我想要一个 TPCT(每个具体类型的表)结构,所以不会有表,但如果我想引用 ,Result我想将链接保留在表中,所以现在我尝试只使用 TPT 结构。我发现 TPCT 更干净,但最终如果 TPT 是实现我想要的目标的唯一方法,我就同意了。ActionResult我已经为我的模型结构尝试了以下变体:public class Action {    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]    public int Id {get; set;}    public int Result_Id {get; set;}    [ForeignKey("Result_Id")]    public virtual Result Result {get; set;}    public string Description {get; set;}}public abstract class Result{    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]    public int Id {get; set;}    [Required]    public int Action_Id {get; set;}    [ForeignKey("Action_Id")]    public virtual Action Action {get; set;}    public string Comment {get; set;}    public class Approved : Result    {        public string Thing {get; set;}    }    public class Rejected : Result    {        public string Stuff {get; set;}    }    public class Modified : Result    {        public string Whatever {get; set;}    }}然后我在上下文文件中尝试了以下 2 种策略来实现 TPT:modelBuilder.Entity<Approved>().ToTable("Approved");modelBuilder.Entity<Rejected>().ToTable("Rejected");modelBuilder.Entity<Modified>().ToTable("Modified");或者对于 TCPT:modelBuilder.Entity<Approved>().Map(m =>{    m.MapInheritedProperties();    m.ToTable("Approved");});每次我尝试添加新的迁移时,无论我尝试什么,我都会遇到以下错误: Unable to determine the principal end of an association between the types 'Result' and 'Action'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.我能够让它工作的一次是如果我从课堂上删除了这个引用Action:public int Result_Id {get; set;}[ForeignKey("Result_Id")]public virtual Result Result {get; set;}但我真的很想保留该引用,这样当我进入数据库获取该Action对象时,我可以立即判断是否存在Result与其关联的对象,而无需遍历所有 3 个结果表来查看是否存在关联对象。参考这一点Action(这就是为什么我认为我需要 TPT...)
查看完整描述

1 回答

?
哔哔one

TA贡献1854条经验 获得超8个赞

经过大量的研究和反复试验,我发现了需要什么才能得到我想要的结果。它是TPCT DB结构,并且该Action对象能够保留对Result. 以下是模型类:


public class Action 

{

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

    public int Id {get; set;}


    public virtual Result Result {get; set;} //just virtual here, as Action is the dependent and Result is the principal-- i.e. this Result isn't required


    public string Description {get; set;}

}


public abstract class Result

{

    //got rid of the Result_Id, since it's 1:1 the Action_Id can be the Key


    [Required, Key] //added "Key"

    public int Action_Id {get; set;}


    [ForeignKey("Action_Id")]

    public Action Action {get; set;} //removed this virtual, as Action is Required for Result, that makes Result the principal


    public string Comment {get; set;}



    public class Approved : Result

    {

        public string Thing {get; set;}

    }


    public class Rejected : Result

    {

        public string Stuff {get; set;}

    }


    public class Modified : Result

    {

        public string Whatever {get; set;}

    }

}

以下是上下文中的流畅 API 代码:


//this gave me TPCT like I wanted

modelBuilder.Entity<Approved>().Map(m =>

{

    m.MapInheritedProperties();

    m.ToTable("Approved");

});


modelBuilder.Entity<Rejected>().Map(m =>

{

    m.MapInheritedProperties();

    m.ToTable("Rejected");

});


modelBuilder.Entity<Modified>().Map(m =>

{

    m.MapInheritedProperties();

    m.ToTable("Modified");

});


//this defined the principal-dependent relationship I was missing

modelBuilder.Entity<Action>()

    .HasOptional(a => a.Result)

    .WithRequired(a => a.Action)

    .Map(x => x.MapKey("Action_Id"));

然后就成功了!希望这个例子可以帮助其他人。


查看完整回答
反对 回复 2023-08-13
  • 1 回答
  • 0 关注
  • 102 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信