2009-06-18 8 views
2

J'ai deux tables:Comment insérer des enregistrements dans une relation maître/détail

OutputPackages (maître)

|PackageID| 

OutputItems (détail)

|ItemID|PackageID| 

OutputItems a un indice appelé « idxPackage 'défini sur la colonne PackageID. ItemID est réglé sur l'incrémentation automatique.

Voici le code que je utilise pour insérer maîtres/détails dans ces tableaux:

//fill packages table 
for i := 1 to 10 do 
begin 
    Package := TfPackage(dlgSummary.fcPackageForms.Forms[i]); 

if Package.PackageLoaded then 
begin 
    with tblOutputPackages do 
    begin 
    Insert; 
    FieldByName('PackageID').AsInteger := Package.ourNum; 
    FieldByName('Description').AsString := Package.Title; 
    FieldByName('Total').AsCurrency := Package.Total; 
    Post; 
    end; 

    //fill items table 
    for ii := 1 to 10 do 
    begin 
    Item := TfPackagedItemEdit(Package.fc.Forms[ii]); 
    if Item.Activated then 
    begin 
     with tblOutputItems do 
     begin 
     Append; 
     FieldByName('PackageID').AsInteger := Package.ourNum; 
     FieldByName('Description').AsString := Item.Description; 
     FieldByName('Comment').AsString := Item.Comment; 
     FieldByName('Price').AsCurrency := Item.Price; 
     Post; //this causes the primary key exception 
     end; 
    end; 
    end; 
end; 

Cela fonctionne bien aussi longtemps que je ne plaisante pas avec les propriétés MasterSource/MasterFields dans l'EDI. Mais une fois que je l'ai défini, et que j'exécute ce code, j'obtiens une erreur qui indique que j'ai une clé primaire en double 'ItemID'.

Je ne suis pas sûr de ce qui se passe - c'est ma première incursion dans master/detail, donc quelque chose peut être mal configuré. J'utilise la base de données absolue de ComponentAce pour ce projet.

Comment puis-je l'insérer correctement?

Mise à jour

Ok, je l'ai enlevé la clé primaire retenue dans ma db, et je vois que pour une raison quelconque, la fonction d'auto-incrémentation de la table OutputItems ne fonctionne pas comme je m'y attendais. Voici comment la table OutputItems semble après avoir exécuté le code ci-dessus:

ItemID|PackageID| 
1  |1  | 
1  |1  | 
2  |2  | 
2  |2  | 

Je ne vois toujours pas pourquoi toutes les valeurs Itemid ne sont pas uniques .... Des idées?

+0

Quelle ligne de votre routine provoque cette exception? De même, comment les propriétés MasterSource/MasterFields sont-elles configurées dans l'EDI? –

+0

J'ai modifié le code pour montrer où se trouvait l'exception. Dans l'EDI: tblOutputItems.MasterSource = dsOutputPackages tblOutputItems.IndexName = idxPackage tblOutputItems.MasterFields = ID du paquet – croceldon

Répondre

2

Est-ce que l'utilisation d'insérer plutôt que d'ajouter sur la table des éléments se comporte différemment? Ma conjecture ici est que l'append sur le détail "voit" un jeu de données vide, ainsi la logique d'auto-incrément commence à un, l'enregistrement suivant deux, etc. même si ces valeurs ont déjà été assignées ... juste à une autre fiche principale .

Une solution que j'ai utilisée dans le passé était de créer une nouvelle table nommée UniqueNums qui persistait le prochain numéro d'identification d'enregistrement disponible que j'allais utiliser. Comme j'ai utilisé un nombre, je verrouiller cette table, incrémenter la valeur et l'écrire puis déverrouiller et utiliser. Cela pourrait vous aider à contourner le problème spécifique que vous rencontrez.

+0

J'ai essayé d'utiliser l'insert, mais cela ne faisait aucune différence. En fait, j'utilisais l'insert en premier - j'ai seulement essayé d'utiliser append après avoir eu des problèmes. – croceldon

0

Tout d'abord, l'idée de l'auto-incrémentation et la définition des ID par code se contredisent selon moi. Le chemin à parcourir est de générer la clé vous-même dans le code. Surtout avec les applications multi-utilisateurs qui nécessitent des insertions maître/détail, il est difficile d'obtenir la bonne clé insérée pour les détails.

Générez donc un ID par code. Lors de la conception de la table, définissez le champ ID sur la clé primaire, mais pas d'incrémentation automatique. Si je ne me trompe pas, Append est utilisé pour l'opération.

Egalement, vous semblez itérer alors que les contrôles visuels sont activés? (Item.Activated). Mais l'opération est un processus par lots par nature. Pour les performances de l'interface utilisateur, vous devez envisager de désactiver les contrôles DB qui sont connectés, puis d'exécuter l'opération. Étant dans la portée maître/détail, cela peut être le problème que deux autres curseurs ne itérent pas comme prévu.

0

Avez-vous essayé de remplacer Ajouter/Insérer avec Modifier?
Et ignorer le "FieldByName ('PackageID'). AsInteger: = Package.ourNum;" ligne.

Je pense que la relation M/D ajoute automatiquement les enregistrements de détail selon les besoins et définit également les clés primaires de la table de détails.

Cela peut également être la raison de l'erreur de clé primaire en double. L'enregistrement est déjà créé par la relation M/D lorsque vous essayez d'ajouter/insérer un autre.