【问题标题】:Many to Many "self"-relation SQLite: is it possible?多对多“自我”关系SQLite:有可能吗?
【发布时间】:2017-02-17 14:42:09
【问题描述】:


我正在使用 SQLite.net 和 SQLite-Net Extensions。我想创建多对多的自我关系。
就我而言,我有一个带有一些兄弟姐妹的子类,当然兄弟姐妹仍然是儿童类型。因此我尝试实现多对多关系:

子类

[ManyToMany(typeof(Brotherhood), CascadeOperations = CascadeOperation.All)]
public List<Child> Siblings_DB { get; set; }

兄弟会班

class Brotherhood
{
    [ForeignKey(typeof(Child))]
    public int ID_child1 { get; set; }

    [ForeignKey(typeof(Child))]
    public int ID_child2 { get; set; }

}

这应该是所有的工作。
然后我创建一个Child 并在Siblings 列表中添加一个兄弟姐妹,但是当我尝试使用InsertOrReplaceWithChildren(Child,true) 将类保存在数据库中时,只有ID_child1 被更新并且ID_child2 保持为0。
任何想法?我做错了什么?
亚历克斯

【问题讨论】:

标签: c# database sqlite many-to-many sqlite-net-extensions


【解决方案1】:

数据库架构必须首先与您尝试执行的操作兼容。 every 关系的一侧必须是一个键(唯一)属性或一组属性,所以不,你不能自己拥有多对多的自我关系。但是,如果您创建另一个表来保存相关行,并且组合键包含您尝试在其上创建关系的一个表中的键属性 [s] 的两个副本,那么您可以这样做。

假设表键是myPK,然后创建一个名为myM2M 的第二个表,其主键包含属性myPK1myPK2,它们共同构成了这个新表的pk,然后在这两个列与第一个表中的myPK 列之间形成关系。

你看过this吗?

【讨论】:

  • 我的范围是使用 ORM 来创建这种关系,而不是使用原始 SQLite 语言。如果多对多的关系是在两个不同的类之间完成的,那么一切都有效。此外,我已经创建了“第二张”表:兄弟情谊,应该实现多对多关系。当我使用同一个类时出了点问题。我会看例子thx
【解决方案2】:

在我设法实现多对多自我关系的一些尝试之后,我对在同一个类中有两个多对多关系有点困惑:我想知道哪个是“官方”的。终于我明白了,两者都是!而兄弟之和就是两个List之和。

[ManyToMany(typeof(Brotherhood), "ChildID1", "Siblings_DB_support", CascadeOperations = CascadeOperation.All)]
public List<Child> Siblings_DB { get; set; }
[ManyToMany(typeof(Brotherhood), "ChildID2", "Siblings_DB", CascadeOperations = CascadeOperation.All)]
public List<Child> Siblings_DB_support { get; set; }

还有关系表:

public class Brotherhood
{
    [ForeignKey(typeof(Child))]
    public int ChildID1 { get; set; }

    [ForeignKey(typeof(Child))]
    public int ChildID2 { get; set; }
}

【讨论】:

    【解决方案3】:

    在这种情况下,您必须在属性属性中明确指定外键和反向关系。

    public class TwitterUser {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
    
        public string Name { get; set; }
    
        [ManyToMany(typeof(FollowerLeaderRelationshipTable), "LeaderId", "Followers",
            CascadeOperations = CascadeOperation.All)]
        public List<TwitterUser> FollowingUsers { get; set; }
    
        // ReadOnly is required because we're not specifying the followers manually, but want to obtain them from database
        [ManyToMany(typeof(FollowerLeaderRelationshipTable), "FollowerId", "FollowingUsers",
            CascadeOperations = CascadeOperation.CascadeRead, ReadOnly = true)]
        public List<TwitterUser> Followers { get; set; }
    }
    
    // Intermediate class, not used directly anywhere in the code, only in ManyToMany attributes and table creation
    public class FollowerLeaderRelationshipTable {
        public int LeaderId { get; set; }
        public int FollowerId { get; set; }
    }
    

    如果您的关系是“兄弟”而不是“父子”,则必须将两种关系相加,例如:

    public class Person {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
    
        public string Name { get; set; }
    
        [ManyToMany(typeof(BrothersRelationshipTable), "OldBrotherId", "YoungerBrothers",
            CascadeOperations = CascadeOperation.All)]
        public List<Person> OlderBrothers { get; set; }
    
        [ManyToMany(typeof(BrothersRelationshipTable), "YoungBrotherId", "OlderBrothers",
            CascadeOperations = CascadeOperation.CascadeRead, ReadOnly = true)]
        public List<Brothers> YoungerBrothers { get; set; }
    
        [Ignore]
        publc List<TwitterUser> Brothers { 
            get { return YoungerBrothers.Concat(OlderBrothers).ToList() }
        }
    }
    
    // Intermediate class, not used directly anywhere in the code, only in ManyToMany attributes and table creation
    public class BrothersRelationshipTable {
        public int OldBrotherId { get; set; }
        public int YoungBrotherId { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-12
      • 2015-11-11
      • 2019-11-07
      • 1970-01-01
      • 2017-06-10
      相关资源
      最近更新 更多