简体   繁体   English

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

[英]Abstract Class with 1 to 1 relationship Entity Framework

Using entity framework I've been trying to create this relationship. 使用实体框架,我一直在尝试创建这种关系。 Basically I have 1 object which has a Result . 基本上我有1个对象具有Result The Result object is abstract, as it has to be one of the 3 classes that inherit from Result , ie Approved , Rejected , or Modified : Result对象是抽象的,因为它必须是从Result继承的3个类之一,即ApprovedRejectedModified

在此处输入图片说明

I'm trying to create the table structure using Entity Framework. 我正在尝试使用实体框架创建表结构。 Originally I was going for a TPCT (Table Per Concrete Type) structure, so there would be no Result table, but I wanted to keep the link back in the Action table if I wanted to reference the Result , so now I'm attempting just TPT structure. 最初,我打算使用TPCT(每个具体类型的表)结构,所以将没有Result表,但是如果我想引用Result ,我想将链接保留在Action表中,因此现在我只尝试TPT结构。 I find TPCT is cleaner, but ultimately if TPT is the only way to achieve what I want, I'm fine with it. 我发现TPCT更干净,但是最终,如果TPT是实现我想要的唯一途径,那我很好。

I've tried variations of the following for my model structure: 我已经为模型结构尝试了以下变化:

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

And then I've tried the following 2 strategies in my context file to either implement TPT: 然后,我在上下文文件中尝试了以下两种策略来实现TPT:

modelBuilder.Entity<Approved>().ToTable("Approved");
modelBuilder.Entity<Rejected>().ToTable("Rejected");
modelBuilder.Entity<Modified>().ToTable("Modified");

Or for TCPT: 或对于TCPT:

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

Everytime I try to add the new migration, whatever I try, I'm faced with this error: 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. 每当我尝试添加新的迁移时,无论尝试什么,都会遇到此错误: 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. 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.

The one time I was able to have it work was if I removed this reference from in the Action class: 有一次我能使它起作用,是我是否从Action类中删除了此引用:

public int Result_Id {get; set;}

[ForeignKey("Result_Id")]
public virtual Result Result {get; set;}

But I would really like to keep that reference there so then when I go into my DB to grab that Action object, I can immediately tell if there is a Result associated to it, without having to go through all 3 Result tables to see if there is a reference to that Action (which is why I think I need to have TPT...) 但是我真的很想保留该引用,因此当我进入数据库获取该Action对象时,我可以立即判断是否有关联的Result ,而不必遍历所有3个Result表来查看是否存在是对该Action的引用(这就是为什么我认为我需要TPT的原因...)

Any help to get this working would be greatly appreciated! 任何帮助使这项工作将不胜感激!

With a lot of research and trial and error, I discovered what I needed to get the result I wanted. 经过大量的研究和反复试验,我发现了获得所需结果所需的条件。 It's TPCT DB structure, and the Action object is able to keep the reference to Result . 它是TPCT DB结构,并且Action对象能够保留对Result的引用。 Here are the model classes: 这是模型类:

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

And here is the fluent API code from the context: 以下是来自上下文的流畅的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"));

And then it worked! 然后它起作用了! Hopefully this example can assist someone else. 希望这个例子可以帮助其他人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM