[英]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是包含来自A
和B
数据的“超类”。 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
默认值表示列名: AId
和BId
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.