Авто приращение с единицей работы - PullRequest
1 голос
/ 22 апреля 2010

Context

Я строю постоянный слой для абстрагирования различных типов баз данных, которые мне понадобятся. В реляционной части у меня есть MySQL, Oracle и PostgreSQL.

Давайте возьмем следующие упрощенные таблицы MySQL:

CREATE TABLE Contact (
  ID varchar(15),
  NAME varchar(30)
);

CREATE TABLE Address (
  ID varchar(15),
  CONTACT_ID varchar(15),
  NAME varchar(50)
);

Я использую код для генерации специфичного для системы буквенно-цифрового уникального идентификатора, подходящего 15 символов в этом случае. Таким образом, если я вставляю запись контакта с ее адресами, у меня появляются сгенерированные Contact.ID и Address.CONTACT_ID перед фиксацией.

Я создал Единицу работы (среди прочих) согласно шаблонам Мартина Фаулера для добавления поддержки транзакций. Я использую Identity Map на основе ключей в UoW для отслеживания измененных записей в памяти. Это работает как очарование для сценария выше, все довольно стандартные вещи до сих пор.

Сценарий вопроса возникает, когда у меня есть база данных, которая не находится под моим контролем, и поля идентификатора имеют автоинкремент (или в последовательностях Oracle). В этом случае у меня нет сгенерированного db Contact.ID заранее, поэтому при создании моего адреса у меня нет значения для Address.CONTACT_ID. Транзакция не была запущена в сеансе БД, поскольку все они хранятся в карте идентификации в памяти.

Вопрос: Какой хороший подход для решения этой проблемы? (Избегая ненужных поездок по БД)

Некоторые идеи: Получить последний идентификатор: я могу позвонить в базу данных, чтобы получить последний идентификатор, например:

SELECT Auto_increment FROM information_schema.tables WHERE table_name='Contact'; 

Но это специфично для MySQL, и, вероятно, что-то подобное можно сделать для других баз данных. Если это сделать, необходимо выполнить первую вставку, получить идентификатор и затем обновить дочерние элементы (Address.CONTACT_IDs) - все в контексте текущей транзакции.

1 Ответ

1 голос
/ 22 апреля 2010

Избегайте явной ссылки на CONTACT_ID полностью.Предполагая, что Contact.NAME имеет ограничение UNIQUE и что столбец CONTACT_ID REFERENCES Contact(ID):

INSERT INTO Contact (NAME) VALUES ('Joe Bloggs'); -- Contact.ID auto-generated
INSERT INTO Address (CONTACT_ID, NAME)
     VALUES ((SELECT ID FROM Contact WHERE NAME = 'Joe Bloggs'),
             '123 Apple Lane');

Теперь Address.CONTACT_ID является правильным, если ваш код не знает значение ключа или даже его тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...