简体   繁体   English

少林一对一关系

[英]One-to-one relation in Shaolinq

I am using Shaolinq library for database usage and I have problem with one-to-one relation. 我正在使用Shaolinq库进行数据库使用,并且一对一关系存在问题。 I have following database schema: 我有以下数据库架构:

create table A (
    Id INT NOT NULL,
    PRIMARY KEY (`Id`)
);
create  table B (
    Id INT NOT NULL,
    PRIMARY KEY (`Id`),
    CONSTRAINT `fk_a_b_id` FOREIGN KEY (`Id`) REFERENCES `A` (`Id`)
);

basically those two tables contains info about same things, just different data. 基本上,这两个表包含有关相同内容的信息,只是不同的数据。 That's how someone has designed it, I cannot change it. 那是有人设计的方式,我无法更改。

However, in the code I would like to have all those data in one object. 但是,在代码中,我希望将所有这些数据放在一个对象中。 I have been trying with BackReference, but no luck: 我一直在尝试BackReference,但没有运气:

[DataAccessObject]
public abstract class A : DataAccessObject<uint>
{
    [AutoIncrement]
    [PersistedMember]
    public abstract uint Id { get; set; }

    [RelatedDataAccessObjects]
    public abstract RelatedDataAccessObjects<B> Bs { get; }
}

[DataAccessObject]
public abstract class B : DataAccessObject
{
    [BackReference(Name = "", PrefixName = "", SuffixName = "")]
    public abstract A Id { get; set; }

    [PersistedMember]
    public abstract string MoreData { get; set; }
}

This created somehow similar schema (obviously Id in B is not primary key now), but after I fill data in DB, Bs property in A is not filled with references. 这创建了某种相似的模式(显然B中的Id现在不是主键),但是在我将数据填充到DB中之后,A中的Bs属性未填充引用。 Simply puting abstract property of type B in A also doesn't seem to work since same column is foreign key and primary key at once (Id). 简单地将类型B的抽象属性放在A中似乎也不起作用,因为同一列同时是外键和主键(Id)。

Any advice is welcome. 欢迎任何建议。

Do you need to access a collection of Bs from As? 您是否需要从As访问B的集合? It seems to me that B is the "super class" that encompasses data from both A and B . 在我看来,B是包含来自AB数据的“超类”。 If that's the case, then you can just make A the primary key of B . 如果是这样,那么您只需将A作为B的主键即可。

[DataAccessObject]
public abstract class A : DataAccessObject<uint>
{
    [PersistedMember(Name = "Id")]
    public abstract override uint Id { get; set; }

    [PersistedMember]
    public abstract string Data { get; set; }
}

[DataAccessObject]
public abstract class B : DataAccessObject<A>
{
    [PersistedMember(Name = "Id", PrefixName = "")]
    public abstract override A Id { get; set; }

    [PersistedMember]
    public abstract string MoreData { get; set; }
}

Note that I've overridden the Id properties to get the column names matching the SQL. 请注意,我已重写Id属性以获取与SQL匹配的列名。 The defaults have meant column names: AId and BId 默认值表示列名: AIdBId

Because the primary key is an object it's known in Shaolinq terminology as a "complex primary key". 因为主键是一个对象,所以在Shaolinq术语中将其称为“复杂主键”。 You can use the deflated references feature to retrieve objects just be their primary key without a roundtrip to the database (more here: https://github.com/tumtumtum/Shaolinq/wiki/Deflated-References ) 您可以使用放气的引用功能来检索对象,而只需将它们作为它们的主键即可,而无需往返数据库(更多信息: https : //github.com/tumtumtum/Shaolinq/wiki/Deflated-References

You can query for a specific value of B: 您可以查询B的特定值:

// Need to define primary key using an anonymous object because it's not an uint but rather an A that contains an uint.
model.Bs.GetByPrimaryKey(new { Id = 100 } );

You can also query for a specific value of B using a deflated reference: 您还可以使用放气的引用查询B的特定值:

model.Bs.GetByPrimaryKey(model.As.GetReference(100));

You can also use references within normal LINQ queries: 您还可以在普通的LINQ查询中使用引用:

model.Bs.Where(c => c.Id == model.As.GetReference(100) || c.Id == model.As.GetReference(101)).ToList();

You can directly access nested/complex primary keys within the query too: 您也可以直接在查询中访问嵌套/复杂的主键:

model.Bs.Where(c => c.Id.Id == 100 || c.Id.Id == 101).ToList();

Note that the above three queries don't need to perform an implicit join be cause the complex primary key is flattened out and stored on the table B . 请注意,由于复杂的主键被展平并存储在表B上,因此上述三个查询不需要执行隐式联接。

When you get back B , you can access B.Id.Id without a round-trip query but if you access B.Id.Data then that will cause B.Id to automatically inflate with a hidden round-trip to the database. 当你回到B ,你可以访问B.Id.Id不用往返查询,但如果你访问B.Id.Data那么这将导致B.Id到自动隐藏往返到数据库膨胀 To avoid this, you can use Include to automatically inflate B.Id with the first query. 为避免这种情况,您可以使用Include在第一个查询中自动为B.Id充气。

model.Bs.Include(c => c.Id).Single(c => c.Id == model.As.GetReference(100));

Or more succinctly: 或更简洁地说:

model.Bs.Include(c => c.Id).Single(c => c.Id.Id == 100);

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

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