Laden...

Tabellen Beziehung führt zu einem nicht zulässigen Zyklischen Verweis.

Erstellt von Palladin007 vor 11 Jahren Letzter Beitrag vor 11 Jahren 4.028 Views
Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren
Tabellen Beziehung führt zu einem nicht zulässigen Zyklischen Verweis.

verwendetes Datenbanksystem: MsSQL

Hi

Ich habe jetzt zwei Tage an einem Datenbank-Konzept gearbeitet, alles fein säuberlich aufgezeichnet, habe dann jede Tabelle im Visual Studio Server-Explorer geschrieben und wollte die Beziehungen eintragen, als ich folgenden Fehler bekam:

Die referenzielle Beziehung führt zu einem nicht zulässigen Zyklischen Verweis.

Um zu zeigen, wie ich das grundlegend aufgebaut habe, zeige ich drei Tabellen, die dem gleichen Grundprinzip folgen, wie die meisten Tabellen im meinem Konzept und unter anderem auch die Tabellen, bei denen der Fehler auf tritt:

[Bild im Dateianhang]

Das sind die drei Tabellen, die das Grundprinzip beschreiben. Das Bild hab ich mit LINQ to SQl gemacht, weil es schön einfach zu gestalten ist, die Frage bezieht sich aber auf das reine MsSQL im Server-Editor vom Visual Studio.

Ich möchte damit eine Art Liste erhalten aufbauen können.
Account ist, wie der Name schon sagt, ein einfacher Account.
FriendCollection ist eine Tabelle, die nur dazu dient, mehrere Accounts in eine Auflistung zu bringen, die dann, verknüpft über die ID von CollectionBinding, mit der Spalte FriendCollectionID mit der Tabelle Account in Beziehung.

Als Beispiel mal diese Daten:

Account

ID  |  Name   |  FriendCollectionID
---------------------------------------
 1  |  Hans   |  5
 1  |  Niels  |  6
CollectionBinding

ID
---------------------------------------
 5
 6
Account

ID  |  CollectionID  |  AccountID
---------------------------------------
 1  |  5             |  7
 2  |  5             |  3
 3  |  5             |  10
 4  |  5             |  5
 6  |  6             |  15
 7  |  6             |  37
 8  |  6             |  562
 9  |  6             |  4

Auf diese Weise hat Hans die Freunde mit den IDs 7, 3, 10 und 5.
Niels hat die Freunde mit den IDs 15, 37, 562 und 4.

Das ist so umständlich notwendig, damit ich ein gleich bleibendes Prinzip verwenden kann, da ich auch Tabellen habe, die eine Auflistung besitzen die Elemente der selben Tabelle listen.

Die Tabelle CollectionBinding habe ich nur einmal und alle weiteren Tabellen verwirklichen ihre Auflistung über diesen Umweg.

Wenn ich nun die Beziehung zwischen Account und CollectionBinding so setze:
CollectionBinding ist die Primärschlüssel-Tabelle und ID der Schlüssel
Account ist die Fremdschlüsseltabelle und FriendCollectionID der Fremdschlüssel
gibt es den Fehler, den ich oben aufgeschrieben habe.

Zusätzlich hatte ich noch vor, die Beziehung zwischen den Tabellen FriendCollection und CollectionBinding auf die gleiche Art zu setzen, nur dass diesmal FriendCollection die Fremdschlüsseltabelle ist und CollectionBinding der Fremdschlüssel.

Ich möchte dabei eine Fremdschlüsseleinschränkung haben und setze dafür bei beiden Tabellen auf cascade.

Worin liegt der Fehler und wie kann ich das ändern?
Oder ist mein Ansatz falsch? Muss ich diese Fremdschlüsseleinschränkung händisch im Code ermöglichen, denn der Fehler tritt nur auf, wenn ich das auf cascade setze, oder wie kann ich das machen?

Gruß

PS: Das ist meine erste größere Datenbank, die ich schreibe, ich habe also eigentlich kaum Erfahrung damit. Würde mich also freuen, wenn ihr mir da etwas Anfänger-Gerecht helfen könnt.

.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

1.378 Beiträge seit 2006
vor 11 Jahren

So ein System hab ich noch nie gesehen und es macht auch (zumindest in dem kleinen Beispiel hier) für mich keinen Sinn.

Was du hier erreichen willst ist eine klassische M:N Beziehung, welche durch eine Beziehungstabelle abgebildet wird:


ID  |  Name 
--------------
 1  |  Hans  
 1  |  Niels  


ID1  |  ID2
--------------
 5    |    7
 5    |    3
 5    |    10
 6    |    15
 6    |    37
 6    |    562
 6    |    4

Und die Beziehung wäre:

Friendcollection.ID1 -> Account.ID

und

Friendcollection.ID2 -> Account.ID

somit kann jeder Account beliebig viele andere Accounts als Freund haben. 😃

Lg, XXX

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren

Ja, so hatte ich das ursprünglich auch, da ich aber auch ein Nachrichten-System drin habe, das die Ordner Inbox, Outbox und Papierkorb speichert, gibt es da ein Problem.

Dann alle drei Auflistungen beinhalten Daten der selben Tabelle und die sollen getrennt bleiben.
Damit funktioniert die einfache M:N-Beziehung nicht mehr.

Ich habe das Konzept dann auf alles übertragen, damit ich nicht verschiedene Systeme enthalten habe sondern alles im Prinzip gleich funktioniert.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

1.378 Beiträge seit 2006
vor 11 Jahren

Ich glaub jetzt hab ich dich verstanden:

Du hast aus meiner Sicht nur ein Beziehungsproblem bei der ersten Tabelle:



ID  |  Name
------------
 1  |  Hans
 1  |  Niels


ID
---------------------------------------
 5
 6

 
ID  |  CollectionID  |  AccountID
---------------------------------------
 1  |  5             |  1

 2  |  5             |  7
 3  |  5             |  3
 4  |  5             |  10
 5  |  5             |  5

 6  |  6             |  2

 7  |  6             |  15
 8  |  6             |  37
 9  |  6             |  562
10  |  6             |  4

und die Beziehungen sehen dann genau so wie die Spaltenbezeichnungen aus:

CollectionAccount.CollectionID=>Collection.ID
CollectionAccount.AccountID=>Account.ID

Lg, XXX

/EDIT: Die Collection Spalte von der Account tabelle kannst du dir sparen, weil du den Account einfach auch in die Gruppe rein tust - siehe "hervorgehobene" Einträge in der CollectionAccount Tabelle

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren

Ja, so direkt habe ich das noch gar nicht gemacht, obwohl ich das so machen wollte.

Ich muss doch auch die ID von CollectionBinding an den Account binden, damit von dort aus über diese ID alle Accounts abrufbar sind, mit denen er befreundet ist. Also eine dritte Beziehung, die die Auflistung an den Account bindet und die funktioniert nicht, wenn ich das auf cascade setze.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

1.378 Beiträge seit 2006
vor 11 Jahren

Nein, siehe mein "edit"^^.

Die Abfrage, welcher Account ist mit wem befreundet sieht dann so aus:


select a1.*
from Account a1
join CollectionAccount ca1 on ca1.AccountID=a1.ID
join CollectionAccount ca2 on ca1.CollectionID=ca2.CollectionID and ca1.AccountID<>ca2.AccountID
join Account a2 on ca2.AccountID=a2.ID
where a2.Name='Hans'

und schon bekommst du alle Freunde von Hans.

Lg, XXX

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren

Du meinst, dass für jede Auflistung der erste Eintrag immer der "Besitzer" der Freunde ist?

Ja, würde funktionieren, bringt aber an einer anderen Ecke in der Datenbank auch ein Problem, da ich in mehreren Tabellen eine reine Text-Auflistung habe. Hauptsächlich eine Liste von Informationen, die der Nutzer frei eingeben kann. Ich möchte das als Liste haben, da das dann einfacher zu bearbeiten ist und ich keine Trennzeichen für einzelne Zeilen brauche, die den Nutzer dann wieder einschränken würden.

PS:

Kannst du deinen Code bitte in LINQ übersetzen?
Habs so versucht zu kapieren, aber bisher kenne ich eigentlich nur LINQ und damit werde ich die Datenbank dann auch nutzen.

Was mir dabei einfällt: Kann ich das ganze Beziehungs-Chaos in der reinen SQL-Datenbank auch sein lassen, wenn ich das im LINQ fest lege, oder muss das dort dennoch drin sein?
Ich würde dabei ungern die Fremdschlüsselbeziehung missen, weil ich die dann händisch im Code eingeben muss.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

1.378 Beiträge seit 2006
vor 11 Jahren

Wenn du einen Besitzer wissen willst, kannst du eine weitere Spalte einführen, welches diesen kennzeichnet.

Dein zweites Problem hört sich nach einem neuen Problem an, welches mit dem ersten nichts zu tun hat.

Prinzipiell empfiehlt es sich schon wenn man mit Datenbanken arbeitet auch die Grundlagen von Entities und Relations kurz ERM zu verstehen.

In Linq2Entities würde so eine Abfrage dann ca. so aussehen:

Account hans = .... //Lade Hans 

IEnumerable<Account> freunde = hans.CollectionAccount.Accounts;

oder


IEnumerable<Account> freundeVonHans = dataContext.Accounts.Where(a=>a.Name=="Hans").SelectMany(a=>a.CollectionAccount.Accounts);

Lg, XXX

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren

Wenn du einen Besitzer wissen willst, kannst du eine weitere Spalte einführen, welches diesen kennzeichnet.

Das verstehe ich nicht, wie du das meinst.
Die ID des Accounts ist ja die ID, die speziell in der Tabelle Account zu finden ist.

Wenn ich aber im Account noch Informationen als Auflistung haben will und in einer weiteren Tabelle eine Auflistung, die ebenfalls nur Text enthält, bietet es sich doch an, die gleiche Tabelle, z.B. TextCollection zu nutzen, weil die dafür gedacht ist, eine Auflistung mit Text zu beinhalten.

Damit würde dann das Prinzip, wie du es meintest, nicht mehr funktionieren, oder habe ich das falsch verstanden?

Zu LINQ:
Das in LINQ zu bekommen dürfte eigentlich nicht das Problem sein. Mit dem Tool SQLMetal kann ich das ja machen lassen und passe das Ergebnis nur noch an.
Ich weiß bloß nicht, ob sich in LINQ to SQL auch solche Fremdschlüsselbeziehungen einbauen lassen, ohne dabei das direkt als Code machen zu müssen. Meines Wissens nach nicht, deshalb will ich das in der SQL-Datenbank direkt haben.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

1.378 Beiträge seit 2006
vor 11 Jahren

Die Besitzerspalte:

 
ID  |  CollectionID  |  AccountID | IstBesitzer
---------------------------------------
 1  |  5             |  1     | Ja

 2  |  5             |  7     | Nein
 3  |  5             |  3     | Nein
 4  |  5             |  10    | Nein
 5  |  5             |  5     | Nein

 6  |  6             |  2     | Ja

 7  |  6             |  15    | Nein
 8  |  6             |  37    | Nein
 9  |  6             |  562   | Nein
10  |  6             |  4     | Nein

Ich möchte an dieser Stelle auch erwähnen, dass deine Namensgebung etwas unschön ist und man daraus schwer ein System verstehen kann. Gib den Tabellen sprechende Namen - was soll eine TextCollection sein?

Du meinst jeder Account kann zusätzlich mehrere Texte abspeichern? Dann erstellst du dazu eine neue Tabelle die für die Texte zuständig ist:


ID  |  AccountID  |  Text
----------------------------
 1   |        1         |  bla
 2   |        1         |  anderer Text usw.

Und mittlerweile muss ich auch noch auf [Hinweis] Wie poste ich richtig? 1.1.1 Nicht nach Grundlagen fragen hinweisen. Deine Probleme hier sind alle der Natur mangelndes Verständnis relationaler Datenbanken. Lies dich vielleicht zur Unterstützung in das Thema ERM ein.

Lg, XXX

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren

Eine TextCollection ist eine Sammlung von Text^^
Ich hab die Tabelle mit eingebaut, damit ich nicht mehrere Tabellen haben, die im Prinzip alle die gleiche Aufgabe haben: Text listen
Ich habe zwar mehrere Tabellen die eine Sammlung von Text beinhalten, aber im Prinzip ist die Sammlung von Text, was da auch immer drin steht, immer das gleiche, es gibt nur einen anderen Besitzer.

Das funktioniert aber leider auch nur, wenn ich das alles über den Weg CollectionBinding mache.

Theoretisch müsste das doch eigentlich auch funktionieren, auch wenn das eventuell nicht unbedingt die beste Lösung ist.
Deshalb ja die Frage, ich verstehe den Fehler nicht.

Natürlich kann ich die Text-Listen auch auf mehrere Tabellen für den jeweiligen Besitzer auf teilen. Das ist wahrscheinlich zwar einfacher, aber den Fehler verstehe ich deshalb ja trotzdem noch nicht.

Ja, dass die Fragen zum LINQ Anfängerfragen sind, akzeptiere ich, aber wenn meine bisherige Frage zu dem Fehler sich so einfach nach lesen lässt, dann muss ich echt an mir zweifeln, denn im Internet war der einzige sinnvolle Eintrag in diesem Forum zu finden und das hat mir auch nicht weiter geholfen.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.