【问题标题】:Multiple @OneToOne on same object with SQLite.Net.Async Extensions PCL 1.3.0?使用 SQLite.Net.Async Extensions PCL 1.3.0 在同一对象上有多个 @OneToOne?
【发布时间】:2015-09-24 00:57:12
【问题描述】:

是否可以在使用 SQLite.Net.Async Extensions PCL 1.3.0 的实体中拥有多个 OneToOne 关系?

例子:

[Table("body")]
public class Body
{
    [OneToOne(CascadeOperations = CascadeOperation.All)]
    [Column ("left")]
    public Hand Left { get; set; }

    [OneToOne(CascadeOperations = CascadeOperation.All)]
    [Column ("right")]
    public Hand Right { get; set; }
}

[Table("hand")]
public class Hand
{
    // In this I do not need a reference back to Body.
}

我一直在尝试使用以下答案:

SQLite-Net Extension both one-to-one and one-to-many relationships between two entities

并以这些网站为灵感:

https://bitbucket.org/twincoders/sqlite-net-extensions/overview

https://bitbucket.org/twincoders/sqlite-net-extensions/src/65a1f8519347c40c948855cfc1a1d4d8bbcc8748/Tests/ReflectionExtensionsTests.cs?at=master&fileviewer=file-view-default

不幸的是,到目前为止没有运气。有可能吗?

【问题讨论】:

    标签: sqlite xamarin sqlite-net sqlite-net-extensions


    【解决方案1】:

    是的,这完全有可能,不幸的是你不能依赖自动外键和反向关系发现,所以你需要手动指定它。

    例如,对于int 的主键和外键声明为在同一类中:

    public class Body
    {
        [OneToOne(foreignKey: "LeftId", CascadeOperations = CascadeOperation.All)]
        public Hand Left { get; set; }
    
        [OneToOne(foreignKey: "RightId", CascadeOperations = CascadeOperation.All)]
        public Hand Right { get; set; }
    
        // Foreign key for Left.Id
        public int LeftId { get; set; }
        // Foreign key for Right.Id
        public int RightId { get; set; }
    }
    
    public class Hand
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
    }
    

    如果您的外键在Hand 对象中声明,则属性属性是等效的:

    public class Body
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
    
        [OneToOne(foreignKey: "LeftId", CascadeOperations = CascadeOperation.All)]
        public Hand Left { get; set; }
    
        [OneToOne(foreignKey: "RightId", CascadeOperations = CascadeOperation.All)]
        public Hand Right { get; set; }
    }
    
    public class Hand
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
    
        // Foreign key for Body.Id where this object is Left
        public int LeftId { get; set; }
        // Foreign key for Body.Id where this object is Right
        public int RightId { get; set; }
    }
    

    并且如果需要,必须在两端的OneToOne 属性的inverseProperty 键中指定逆属性:

    public class Body
    {
        // Skipping foreign keys and primary key
    
        [OneToOne(foreignKey: "LeftId", inverseProperty: "LeftBody", CascadeOperations = CascadeOperation.All)]
        public Hand Left { get; set; }
    
        [OneToOne(foreignKey: "RightId", inverseProperty: "RightBody", CascadeOperations = CascadeOperation.All)]
        public Hand Right { get; set; }
    }
    
    public class Hand
    {
        // Skipping foreign keys and primary key
    
        [OneToOne(foreignKey: "LeftId", inverseProperty: "Left", CascadeOperations = CascadeOperation.All)]
        public Body LeftBody { get; set; }
    
        [OneToOne(foreignKey: "RightId", inverseProperty: "Right", CascadeOperations = CascadeOperation.All)]
        public Body RightBody { get; set; }
    }
    

    【讨论】:

    • 谢谢@redent84,我终于用你的例子让它工作了。这两种方法在性能方面是否有任何不同,即在我的情况下,是否更喜欢将外键保留在 Body 或 Hand 中?我实际上只需要 Body 知道两只手,我打算递归查询它们,所以应该认为最好将外键保存在 Body 中? - 一个额外的问题是我什么时候应该查询上述结构,然后我在 GetAllWithChildrenAsync 中设置递归标志。是否可以指定要获取的对象或深度,即获取深度?
    • 性能方面总是更好地通过主键访问对象,因此如果您要从Body递归访问Hands,最好将外键保留在Body中.在这种特定情况下,它也更有意义。至于递归,如果您不需要它,请将CascadeOperations 更改为更保守的东西。目前无法在运行时指定深度,只能基于关系属性的CascadeOperations 属性。
    • “不幸的是,您不能依赖自动外键和反向关系发现” - 就个人而言,我更喜欢这个,不仅是为了提高性能,而且是为了减少猜测和依赖框架来尝试假设基于字符串的东西!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 2023-03-28
    • 1970-01-01
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多