Отношение один к одному в Шаолинь - PullRequest
0 голосов
/ 24 октября 2018

Я использую библиотеку Shaolinq для использования базы данных, и у меня проблема с отношением один к одному.У меня есть следующая схема базы данных:

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`)
);

в основном эти две таблицы содержат информацию об одних и тех же вещах, просто разные данные.Вот как кто-то его спроектировал, я не могу его изменить.

Однако в коде я хотел бы, чтобы все эти данные были в одном объекте.Я пытался с 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; }
}

Это создало похожую схему (очевидно, Id в B сейчас не первичный ключ), но после того, как я заполняю данные в DB, ​​свойство Bs в Aне заполнены ссылками.Простое помещение абстрактного свойства типа B в A также, похоже, не работает, поскольку один и тот же столбец является внешним ключом и первичным ключом одновременно (Id).

Любой совет приветствуется.

1 Ответ

0 голосов
/ 24 октября 2018

Вам нужен доступ к коллекции Bs из As?Мне кажется, что B - это «суперкласс», который включает в себя данные как A, так и 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; }
}

Обратите внимание, что я переопределил свойства Id, чтобы получить имена столбцов, соответствующие SQL.Значения по умолчанию означают имена столбцов: AId и BId

Поскольку первичный ключ является объектом, он известен в терминологии Shaolinq как «сложный первичный ключ».Вы можете использовать функцию дефлированных ссылок для извлечения объектов, просто являясь их первичным ключом без обращения к базе данных (подробнее здесь: https://github.com/tumtumtum/Shaolinq/wiki/Deflated-References)

Вы можете запросить конкретное значение 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 } );

Вы также можете запросить определенное значение B, используя дефлированную ссылку:

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

Вы также можете использовать ссылки в обычных запросах LINQ:

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

Вы можете получить прямой доступвложенные / сложные первичные ключи в запросе тоже:

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

Обратите внимание, что три вышеуказанных запроса не должны выполнять неявное объединение, поскольку сложный первичный ключ сглаживается и сохраняется в таблице B.

Когда вы вернетесь B, вы можете получить доступ к B.Id.Id без запроса туда-обратно, но если вы откроете B.Id.Data, то B.Id автоматически приведет к инфляции со скрытой обратной связью с базой данных. Чтобы избежать этого, вы можете использовать Include для автоматического раздувания B.Id при первом запросе.

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

Или более кратко:

model.Bs.Include(c => c.Id).Single(c => c.Id.Id == 100);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...