sql >> Database >  >> RDS >> Sqlserver

Waarde van primaire sleutel bijwerken met entiteitsraamwerk

Ik heb een Ph.D. in cs - op het gebied van databases, dus dit antwoord zal een beetje anders zijn dan het perspectief van een programmeur. Met alle respect voor Oliver Hanappi, een sleutel kan en zal af en toe veranderen als het geen surrogaatsleutel is. bijv. Een natuurlijke sleutel of een samengestelde sleutel. Bijvoorbeeld. Het is mogelijk om je BSN in de VS te laten wijzigen. Maar veel programmeurs door de jaren heen zouden dit als een onveranderlijke sleutel beschouwen en als zodanig gebruiken. Het is veel gebruikelijker om een ​​samengestelde primaire sleutel die uit externe sleutels bestaat, te wijzigen.

Ik heb te maken met een database die een ternaire relatie heeft. In het bijzonder drie entiteiten (waarbij externe sleutels surrogaat-primaire sleutels zijn in hun respectievelijke tabellen). Om echter de relatie tussen twee entiteiten te behouden terwijl de derde entiteit wordt gewijzigd, is vereist het wijzigen van een deel van de primaire sleutel van de intersectietabel (ook wel een pure join-tabel genoemd op MSDN). Dit is een geldig ontwerp en kan alleen worden verbeterd door de ternaire relatie-intersectietabel te verwijderen en te vervangen door twee binaire relatietabellen (die hun eigen surrogaatsleutels kunnen hebben). EF zou deze boete afhandelen. Deze ontwerpwijziging zou een (Veel->veel)->veel of Ouder1-Ouder2 -> Kind-kleinkind-model maken (als dat niet duidelijk is, lees dan het onderstaande voorbeeld). Entiteitskader zou hier prima mee werken, omdat elke relatie in feite een een-op-veel-relatie is. Maar het is een gek ontwerp vanuit een DB-perspectief. Ik zal je een voorbeeld laten zien waarom.

Bedenk dat Cursus, Klaslokaal en Instructeur aan elkaar zijn gekoppeld in een klas. Klasse kan het volgende bevatten:CourseID, ClassroomID, InstructorID als externe sleutels en een samengestelde primaire sleutel bevatten die alle drie omvat. Hoewel het een duidelijk, beknopt ternair model (3-wegrelatie) is, kunnen we het opsplitsen in binaire relaties. Dit zou twee intersectietabellen opleveren. Het toevoegen van surrogaatsleutels zou als volgt voldoen aan EF:

Class(SurrogateKeyClass , Instructeur-ID , Cursus-ID )

ClassRoomUsed(SurrogateKeyClassroomUsed , SurrogateKeyClass , ClassRoomID )

Het probleem met dit ontwerp is dat we dezelfde cursus en instructeur meerdere keren kunnen koppelen, wat het vorige model vermijdt. Om dit probleem te voorkomen, kunt u een beperking in de database toevoegen voor de uniciteit van de twee ID-velden, maar waarom zou u dit willen doen als u om te beginnen alleen met surrogaatsleutels te maken hebt? Deze oplossing zou echter zo goed werken als ik kan zien. Dit is echter geen logisch databaseontwerp vanwege de onnatuurlijke unieke beperking die vereist is in de DB.

MAAR, als u uw database niet wilt wijzigen of uw database niet kunt wijzigen, is hier een tweede oplossing :Intersectie-/associatietabellen zijn precies dat, koppelingen die twee of meer entiteiten met elkaar verbinden. Als er een verandert, verwijdert u de koppeling en maakt u een nieuwe met de juiste externe sleutels (navigatie-eigenschappen). Dat betekent dat je in geen van de relaties onderliggende entiteiten mag eisen, maar dat is heel gebruikelijk.

Ik zou willen voorstellen dat het Entity Framework (in de toekomst) degenen onder ons die een elegant DB-model kunnen ontwerpen in staat stelt om delen van sleutels in intersectie-/associatietabellen te veranderen wanneer we maar willen!

Nog een gratis voorbeeld:

Denk aan een Student, Course, Grade Association. Via een cijfer worden studenten aan een vak gekoppeld. Meestal is dit een veel-op-veel-koppeling tussen student en een cursus met een extra veld in de associatietabel genaamd grade (associatietabellen hebben payload-gegevens zoals grade, intersectietabellen hebben geen payload en worden in MSDN aangeduid als pure join-tabellen op lease op één plek):

Student(Student-ID , ....)

Cursus(Cursus-ID , ...)

Nemen(StudentID , Cursus-ID , cijfer)

Als iemand een invoerfout maakt vanuit een dropdown en een student in de verkeerde klas plaatst, wil je dat ze dit later wijzigen door de dropdown opnieuw te selecteren en een andere cursus te selecteren. Op de achtergrond moet je het EF-object uit de Takentabel verwijderen en opnieuw maken zonder een cijfer te verliezen als dat er is. Verander eenvoudig de Foreign Key CourseID lijkt me een beter alternatief. Verzin je eigen associatie als deze gekunsteld lijkt, maar als hoogleraar was het voor mij vanzelfsprekend.

Conclusie:als je een reeks relaties hebt, is het misschien beter om trapsgewijze en/of veranderende FK niet toe te staan, maar er bestaan ​​redelijke/logische scenario's waar dit nodig is, zelfs als dit niet wordt aanbevolen als een best practice in algemeen .

Dit probleem kan zich manifesteren met de volgende uitzonderingen, afhankelijk van of u respectievelijk de navigatie-eigenschap of de sleuteleigenschap in het model wijzigt:

Er is een schending van de referentiële integriteitsbeperking opgetreden:een primaire-sleuteleigenschap die deel uitmaakt van de referentiële integriteitsbeperking kan niet worden gewijzigd wanneer het afhankelijke object Ongewijzigd is, tenzij het wordt ingesteld op het hoofdobject van de koppeling. Het hoofdobject moet worden gevolgd en mag niet worden gemarkeerd voor verwijdering.

De eigenschap 'X' maakt deel uit van de belangrijkste informatie van het object en kan niet worden gewijzigd.



  1. Problemen met de postgresql COPY-opdracht met Rails op een andere server

  2. Een door de gebruiker gedefinieerde functie coderen in SQL Server

  3. Entity Developer en ADO.Net Data Providers ondersteunen nu Entity Framework Core 5

  4. Vergelijking van Oracle MySQL, Percona Server en MariaDB