2010-04-21 6 views
1

Contexteincrément automatique avec une unité de travail

Je construis une couche de persistance abstraite différents types de bases de données que je vais avoir besoin. Sur la partie relationnelle, j'ai mySQL, Oracle et PostgreSQL.

Jetons les tables MySQL simplifiées suivantes:

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

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

J'utilise le code pour générer système alpha numérique 15 coupe près du corps ID unique caractères spécifiques dans ce cas. Ainsi, si j'insère un enregistrement Contact avec ses adresses, j'ai mes Contact.ID et Address.CONTACT_IDs générés avant de valider.

J'ai créé un Unit of Work (parmi d'autres) selon Martin Fowler's patterns pour ajouter un support de transaction. J'utilise une carte d'identité basée sur des clés dans le UoW pour suivre les enregistrements modifiés en mémoire. Cela fonctionne comme un charme pour le scénario ci-dessus, tous les trucs assez standard jusqu'à présent.

Le scénario de question vient quand j'ai une base de données qui ne sont pas sous mon contrôle et les champs d'identification sont auto-incrément (ou dans les séquences Oracle). Dans ce cas, je n'ai pas le db généré Contact.ID avance, quand je crée mon adresse, je n'ai pas de valeur pour Address.CONTACT_ID. La transaction n'a pas été démarrée sur la session DB car tout est conservé dans la carte d'identité en mémoire.

Question: Quelle est une bonne approche pour résoudre ce problème? (en évitant les allers-retours inutiles db)

Quelques idées: récupérer le dernier ID: je peux faire un appel à la base de données pour récupérer la dernière Id comme:

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

Mais c'est MySQL spécifique et probablement quelque chose similaire peut être fait pour les autres bases de données. Si faire cela, alors il faudrait faire le 1er insert, obtenir l'ID puis mettez à jour les enfants (Address.CONTACT_IDs) - tous dans le contexte de la transaction en cours.

Répondre

1

Évitez explicitement référence à la toute CONTACT_ID. En supposant que Contact.NAME a une contrainte UNIQUE et que la colonne CONTACT_IDREFERENCES 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'); 

Maintenant Address.CONTACT_ID est correct sans votre code connaître la valeur de la clé ou même son type.

+0

Hmm ... pourrait fonctionner. Catch doit avoir une clé utilisateur, ce que la plupart des schémas auront. Si j'ai de grandes transactions, le SQL généré sera beaucoup plus grand pour plusieurs enregistrements enfants. Mais, je suppose qu'il sauve des voyages à la DB et j'ai toujours l'isolement de transaction. Merci –

Questions connexes