【问题标题】:How to create a foreign key to an entity when that entity is the same as the parent当实体与父实体相同时如何为实体创建外键
【发布时间】:2018-01-16 13:52:29
【问题描述】:

我有这种一对多的关系,个人资料 -> 追随者,我需要一种方式说追随者是某个个人资料(用户)。如何创建结构以便将追随者指定为特定的个人资料?我想我可以只保留个人资料的 id,但我想有一个钥匙回到个人资料实体

这里是“个人资料”和“关注者”实体

这里是suedo代码

public class Profile {
  public virtual ICollection<Follower> Followers { get; set; }    // one to many
}

public class Follower {
    [Key]
    public int FollowerId { get; set; }

    public int ProfileRefId { get; set; }

    // one-to-many here
    [ForeignKey("ProfileRefId")]
    public virtual Profile Profile { get; set; }

    public DateTime Created { get; set; }


    // code that shows the follower is some specific profile/user
    ????

}

【问题讨论】:

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


    【解决方案1】:

    您提到您在个人资料和关注者之间存在一对多的关系。

    通常这意味着每个个人资料都有零个或多个追随者,并且每个追随者都属于一个个人资料。换句话说:追随者个人资料,而不是个人资料。在软件设计方面:Follower 使用 Composition 来描述其与 Profile 的关系。它不使用继承。

    这样做的原因是,如果您有一个配置文件 P1,其中有两个追随者 F1 和 F2,则两个追随者都有指向同一个 P1 的东西。

    效果是,当改变follower F1的Profile的任何一个属性时,follower F2的Profile中的这些属性也会改变。这是预期行为,因为 F1 的配置文件与 F2 的配置文件相同。

    如果您使用继承来为追随者的个人资料部分建模,那么 F1 和 F2 都将拥有自己的个人资料。更改 F1 的配置文件属性不会更改 F2 的配置文件属性。

    如果你真的想要后者,你的设计不是一对多的 关系。稍后看如何实现继承

    Proper configuration of one-to-many relation:

    class Profile
    {
        public int Id {get; set;}
    
        // a Profile has zero or more followers:
        public virtual ICollection<Follower> Followers {get; set;}
        ...
    }
    
    class Follower
    {
        public int Id {get; set;}
    
        // a follower belongs to exactly one Profile (via foreign key ProfileId)
        public int ProfileId {get; set;}
        public virtual Profile Profile {get; set;}
        ...
    }
    

    优点是实体框架会自动将其识别为一对多关系。不需要属性,也不需要流畅的 API。此外:其他开发人员会立即看到您打算设计一对多关系。

    实体框架中的继承

    如果您打算实现继承,有几种策略可以做到这一点。我最常用的是Table-Per-Concrete-Class (TPC).

    在 TPC 中,每个将具有实例化对象的类都有自己的表。该表具有类的属性以及基类的属性。

    这种设计最容易被别人理解,并且提供了最简单的数据库,可以快速检索和更新。对于您要访问的每个对象,只需要一个表。

    除此之外,这完全模仿了继承的软件行为:如果您创建了一个 Follower 对象,该对象将自动具有 Profile 属性。如果您删除 Follower 对象,它的 Profile 属性也会被删除。更改追随者的个人资料属性之一,不会影响任何其他追随者的个人资料属性。

    class Profile
    {
         ... // profile properties
    }
    
    // A Follower IS a Profile:
    class Follower : Profile
    {
        public int Id {get; set;}
        ... // Follower properties
    }
    
    class MyDbContrext : DbContext
    {
        public DbSet<Follower> Followers{get; set;}
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // tell that the Profile base class properties of Follower should be in the
            // Followers table:
            modelBuilder.Entity<Follower>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable(nameof(MyDbContext.Followers));
            });
        }
    

    【讨论】:

    • 我进行了适当的更改以创建正确的一对多关系。但是我的基本问题确实与创建带有两个外键的“跟随者”表有关,这些外键返回到同一个表“配置文件”。其中一个将是父母,另一个密钥将返回到某个随机配置文件(跟随者)。我在这里找到了我想要的东西stackoverflow.com/questions/28570916/…
    • 最好编辑您的问题,以便它真正表达您的问题的基础。 “我的潜在问题”,为什么会有秘密的潜在问题?为什么不把它们写在你的问题中。为什么说你有一对多,而实际上你的问题是你有一个类有两个对另一个表的引用?如果您提出问题,请尝试通过编写正确的要求来帮助回答者,而不是让他们猜测。
    猜你喜欢
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多