Einzigartigen Schlüssel generieren

  • WPF MVVM
  • .NET (FX) 4.5–4.8

Es gibt 31 Antworten in diesem Thema. Der letzte Beitrag () ist von kafffee.

    Tja, das ist schoma kein relationales Datenmodell, sondern "nur" Objektorientiert, und nicht redundanzfrei.
    Könnte sein, dass die Redundanzhaltigkeit mit deinen Problemen zusammenhängt - sorry - ich hab nicht im Blick, was derzeit das genaue Problem ist.


    kafffee schrieb:

    einfach eine Kopie des Datensatzes mit einer ID versehen werden und dann einer der Playlisten zugefügt werden
    Warum eine Kopie? Und wozu die ID?
    Mit ID ist auch nicht ein einzigartiger Schlüssel gemeint, sondern nur die TrackListID? StartID? oder was?
    Unklar ist auch, was mit "mit einer ID versehen" gemeint ist. Also entweder ein Datentyp hat eine ID-Property oder er hat sie nicht. Solch kann man nicht nachträglich dranmachen.

    ErfinderDesRades schrieb:

    Könnte sein, dass die Redundanzhaltigkeit mit deinen Problemen zusammenhängt - sorry - ich hab nicht im Blick, was derzeit das genaue Problem ist.

    Glaub ich weniger. Der Fehler tritt ja auf wenn ich den selben(!) Track zwei Mal adde. Dann nimmt nämlich der zuerst geaddete Track die ID des zweiten an, obwohl ich den ersten nicht ändere...

    ErfinderDesRades schrieb:

    Warum eine Kopie? Und wozu die ID?

    Zur eindeutigen Identifizierung des Tracks. Stell dir vor, der Nutzer spielt einen Track ab. Dann verschiebt er den Track in der Playlist nach oben oder unten. Und wenn jetzt noch zwei Mal der gleiche Track in der Playlist ist, weiss das Programm nicht, welchen Track es als Nächstes abspielen muss. Kopie deshalb, weil nicht der Original-Datensatz die Track-ID bekommen soll, sondern nur die Kopie, die dann der Playlist zugefügt wird...

    ErfinderDesRades schrieb:

    Mit ID ist auch nicht ein einzigartiger Schlüssel gemeint, sondern nur die TrackListID? StartID? oder was?

    Doch, der einzigartige Schlüssel, der TrackListID wäre. StartID soll der höchste Wert der in den Playlist vorhandenen Schlüssel +1 sein. Also wenn man mehrere Male addet, und zwischendurch mal einen Track aus der Playlist entfernt, dass der Schlüssel nicht zwei Mal vergeben wird...

    ErfinderDesRades schrieb:

    Unklar ist auch, was mit "mit einer ID versehen" gemeint ist.

    Der Original-Datensatz hat in der Property TrackListID = Nothing und das soll auch so bleiben. Bei der Kopie, die dann der Playlist zugefügt wird, soll dann diese Property mit einem für diese Playlist einzigartigen Schlüssel gesetzt werden.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    Jo, jetzt versteh ich glaub das Grundproblem - hängt eben mit den Schwächen objektorientierte Datenmodellierung zusammen.
    Dein LösungsAnsatz scheint mir soweit richtig: Du musst leider für die PlaylistItem die Mp3-Items aufdoppeln.
    Ob eine TracklistID nötig ist, binnich unsicher. Das Programm weiss doch, welches Mp3Item es abspielt. Dann kann es dieses doch in der PlayList suchen, und als nächstes das dahinter befindliche abspielen.



    Funzt das, was du in post#18 zeigst? Das könnte man noch sehr vereinfachen.
    Oder sogar umbauen auf meinen TracklistId-freien Ansatz.

    kafffee schrieb:

    Aber das war schon so gedacht von dir oder?:
    Nee, das ist immer wieder dasselbe Objekt. Was ich meinte, war: es gibt 1000 Tracks. Und es gibt die zu-Decks-Hinzufügepakete. Diese Pakete sollen je aus einem Verweis auf einen der 1000 Tracks bestehen und einer eindeutigen ID. Den Decks werden dann nur neue Pakete hinzugefügt, sodass dann eben zum linken Deck je ein neues Paket hinzugefügt wird mit:
    • Verweis auf Track 543 und ID 1
    • Verweis auf Track 999 und ID 2
    • Verweis auf Track 13 und ID 3
    • Verweis auf Track 543 und ID 4
    und dann eben dem rechten Deck:
    • Verweis auf Track 999 und ID 5
    • Verweis auf Track 48 und ID 6
    • Verweis auf Track 13 und ID 7
    • Verweis auf Track 182 und ID 8
    Das wäre mein Datenhaltungsvorschlag. Aber wie das dann vernünftig in der WPF umgesetzt werden kann, weiß ich nicht.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @ErfinderDesRades

    Jou Code aus Post 18 funzt, bis auf die Tatsache, dass wenn ich einen Track mehrfach adde, die anderen (selben) Einträge halt komischerweise im Nachhinein die gleiche ID des (neuen) bekommen.
    So wie du es vorschlägst hatte ich es zuerst, aber dann ist mir eingefallen was passiert wenn ein und derselbe Track mehrfach in der Playlist vorhanden ist...

    @VaporiZed

    Du willst also dass die Playlist nur aus Instanzen einer Datenklasse mit diesen zwei Eigenschaften besteht?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    Jou Code aus Post 18 funzt, bis auf die Tatsache, dass wenn ich einen Track mehrfach adde, die anderen (selben) Einträge halt komischerweise im Nachhinein die gleiche ID des (neuen) bekommen.
    Dann würde ich sagen, der Code funktioniert nicht.
    Ist ja auch klar: Er macht nicht, was du konzipiert hast - nämlich dass jeweils eine Kopie des Mp3Items geadded wird.
    Das sollteste als erstes lösen - dann wird mein/dein ursprünglicher Ansatz wohl auch funzen.

    Eine Kopie erstellt man mit dem Schlüsselwort New, etwa New Mp3Item(). Dann hat man ein neues Mp3Item.
    Und dann muss man sämtliche Properties der Vorlage ins neue Mp3Item kopieren.

    Übrigens brauchst du überhaupt keine Ids, um Objekte eindeutig zu unterscheiden (ausser bei Structures, aber deine Datensätze sind ja Classes). Also bei so Reference-Typen kann jedes Objekt mittels des Is-Operators eindeutig von anderen Objekten unterschieden werden - intern guckt er glaub einfach nach der SpeicherAddresse des objekts.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @kafffee: Ich würde das als sinnvoll erachten, ja. Über diese Datenpakete komme ich an die Trackinfos wie Interpret, Songtitel, Albumname und eben auch an die Plattendeck-TrackID, welche eben ein zusätzliches Merkmal ist, welches aber nix in der Ursprungsklasse zu suchen hat.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed

    Oje, das mach ich ungern. Hab grad mal nachgeschaut, ich hab in meinem Projekt 88 Verweise auf die Playlist, da müsste ich das allermeiste wahrscheinlich wieder ummodeln.

    Aber ich hab neue Erkenntnisse gewonnen:

    ErfinderDesRades schrieb:

    Eine Kopie erstellt man mit dem Schlüsselwort New, etwa New Mp3Item(). Dann hat man ein neues Mp3Item.
    Und dann muss man sämtliche Properties der Vorlage ins neue Mp3Item kopieren.


    Ich hab das mal probiert:

    VB.NET-Quellcode

    1. Private Sub MusiktitelZuPlaylistZufuegen_Execute(obj As Object)
    2. Dim Objekt As ViewModel.MP3FileInfoVM = CType(obj, ViewModel.MP3FileInfoVM)
    3. Dim AudioTrack As New ViewModel.MP3FileInfoVM
    4. AudioTrack = Objekt
    5. AudioTrack.Interpret = "Interpret"
    6. AudioTrack.Musiktitel = "Titel"
    7. Dim StartID As Integer = 1
    8. If Not Deck2IstSelektiert Then
    9. If LayerViewModel.PlattendecksViewModel.DeckLeft.Playlist.Count > 0 Then
    10. StartID = LayerViewModel.PlattendecksViewModel.DeckLeft.Playlist.Max(Function(x) x.TrackListID) + 1
    11. End If
    12. AudioTrack.TrackListID = StartID
    13. LayerViewModel.PlattendecksViewModel.DeckLeft.Playlist.Add(AudioTrack)
    14. Else
    15. If LayerViewModel.PlattendecksViewModel.DeckRight.Playlist.Count > 0 Then
    16. StartID = LayerViewModel.PlattendecksViewModel.DeckRight.Playlist.Max(Function(x) x.TrackListID) + 1
    17. End If
    18. AudioTrack.TrackListID = StartID
    19. LayerViewModel.PlattendecksViewModel.DeckRight.Playlist.Add(AudioTrack)
    20. End If
    21. End Sub


    Da wird tatsächlich dann sogar aus der ListBox, aus der man die Titel man adden tut, dann das entsprechende Item geändert und zeigt dann AudioTrack.Musiktitel = "Titel" an. Das Ganze geht also "rückwärts". Nun die Frage, wie vermeide ich das, ich hab zwar das Schlüsselwort New in Zeile 3 verwendet, aber offensichtlich falsch, denn sonst sollte es ja funktionieren...

    Und:

    ErfinderDesRades schrieb:

    Übrigens brauchst du überhaupt keine Ids, um Objekte eindeutig zu unterscheiden (ausser bei Structures, aber deine Datensätze sind ja Classes). Also bei so Reference-Typen kann jedes Objekt mittels des Is-Operators eindeutig von anderen Objekten unterschieden werden - intern guckt er glaub einfach nach der SpeicherAddresse des objekts.


    Na das wär natürlich das allerbeste. Hab das mal ausprobiert folgendermassen (in einer wie ich denke geeigneten Sub):

    VB.NET-Quellcode

    1. Public Sub EntferneTrackAusPlaylist_Execute(obj As Object)
    2. Dim LoeschListe As New List(Of MP3FileInfoVM)
    3. For Each item In Playlist
    4. If Playlist(PlaylistGewaehlterIndex) Is AktuelleMP3Info Then LoeschListe.Add(item) 'hier verwende ich den Is-Operator
    5. Next
    6. For Each item In LoeschListe
    7. Playlist.Remove(item)
    8. Next
    9. End Sub


    AktuelleMP3Info ist dabei der aktuell abgespielte Track. Leider werden beim Ausführen, wenn ich mehrere (bis auf die Speicheradresse gleiche) geaddet habe, auch alle Einträge rausgelöscht.

    Edit:
    @ErfinderDesRades

    Achso jetzt weiss ich glaub ich wie du meinst. Einfach beim Adden zur Playlist in Zeile 14 alle Properties über den Konstruktor setzen...

    Edit2:

    @ErfinderDesRades

    Yep das funktioniert:

    VB.NET-Quellcode

    1. Private Sub MusiktitelZuPlaylistZufuegen_Execute(obj As Object)
    2. Dim Objekt As ViewModel.MP3FileInfoVM = CType(obj, ViewModel.MP3FileInfoVM)
    3. Dim StartID As Integer = 1
    4. If Not Deck2IstSelektiert Then
    5. If LayerViewModel.PlattendecksViewModel.DeckLeft.Playlist.Count > 0 Then
    6. StartID = LayerViewModel.PlattendecksViewModel.DeckLeft.Playlist.Max(Function(x) x.TrackListID) + 1
    7. End If
    8. LayerViewModel.PlattendecksViewModel.DeckLeft.Playlist.Add(New MP3FileInfoVM(StartID, "", Objekt.Dateiname, Objekt.Tracknummer, Objekt.Interpret, Objekt.Album, Objekt.Musiktitel, Objekt.Dauer, Objekt.Jahr, Objekt.Stream, Objekt.Genre, Objekt.IsFavorite, Objekt.CoverArtPfad, Objekt.BPM, Objekt.Key, Objekt.Takt))
    9. Else
    10. If LayerViewModel.PlattendecksViewModel.DeckRight.Playlist.Count > 0 Then
    11. StartID = LayerViewModel.PlattendecksViewModel.DeckRight.Playlist.Max(Function(x) x.TrackListID) + 1
    12. End If
    13. LayerViewModel.PlattendecksViewModel.DeckRight.Playlist.Add(New MP3FileInfoVM(StartID, "", Objekt.Dateiname, Objekt.Tracknummer, Objekt.Interpret, Objekt.Album, Objekt.Musiktitel, Objekt.Dauer, Objekt.Jahr, Objekt.Stream, Objekt.Genre, Objekt.IsFavorite, Objekt.CoverArtPfad, Objekt.BPM, Objekt.Key, Objekt.Takt))
    14. End If
    15. End Sub


    Aber was natürlich mal wieder klar war: Es zieht einen Rattenschwanz hinter sich her...

    Wenn ich jetzt in meiner "Hauptmusiksammlung" MainModule.InhaltGesamt nach der Datei suche, die gerade abgespielt wird, z.B. wenn ich die Properties der Datei (ViewModel.MP3FileInfoVM) ändern will, dann findet er die natürlich nicht:

    Dim MusikDatenbankIndex As Integer = MainModule.InhaltGesamt.IndexOf(AktuelleMP3InfoOriginal)

    Also das was du da gesagt hast, mit dem Is-Operator, wenn wir das zum Laufen bringen würden, dann wär das ideal. Dafür müsste ich genau verstehen, was du mit Referenztyp meinst. Was mir ein Begriff ist, dass man Argumente mit ByRef übergeben kann, damit diese von der aufgerufenen Sub aus verändert werden können. Nur rufe ich ja keine Sub oder Function auf, sondern adde Tracks zu einer Playlist...

    Ansonsten würde es auch eine Funktion tun, bei der man hier:

    Dim MusikDatenbankIndex As Integer = MainModule.InhaltGesamt.IndexOf(AktuelleMP3InfoOriginal)

    ...beim vergleichen die Properties TrackListID und IsPlayngIcon quasi vernachlässigen kann, also dass die anderen Properties übereinstimmen müssen, aber diese Zwei beim Vergleichen "übersprungen" werden.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    Wenn ich jetzt in meiner "Hauptmusiksammlung" MainModule.InhaltGesamt nach der Datei suche, die gerade abgespielt wird, z.B. wenn ich die Properties der Datei (ViewModel.MP3FileInfoVM) ändern will, dann findet er die natürlich nicht
    Jo, und hier bist du am Ende der Fahnenstange angekommen.
    Nur ein relationales Datenmodell kann diese gewünschte Funktionalität sauber unterstützen.

    Aber vielleicht gehts unsauber noch ein Stückchen weiter: Nu musste iwie bestimmen, wann zwei Mp3Item als gleich angesehen werden sollen - denkbar wäre etwa, wenn sie auf dieselbe Datei verweisen.
    Also suche nicht das Mp3Item, was in der Hauptliste ist in den Playlists - weil es ist ja in der Hauptliste - in den PlayLists sind allenfalls Kopien.
    Sondern suche in den PlayLists nach solchen Mp3Item, die auf dieselbe Datei verweisen wie das Mp3Item der Hauptliste.

    ErfinderDesRades schrieb:

    Also bei so Reference-Typen kann jedes Objekt mittels des Is-Operators eindeutig von anderen Objekten unterschieden werden


    Okay, also das kann ich mir auch abschminken?

    ErfinderDesRades schrieb:

    Jo, und hier bist du am Ende der Fahnenstange angekommen.


    Anosnsten beiss ich halt in den sauren Apfel...

    kafffee schrieb:

    Oje, das mach ich ungern. Hab grad mal nachgeschaut, ich hab in meinem Projekt 88 Verweise auf die Playlist, da müsste ich das allermeiste wahrscheinlich wieder ummodeln.
    - dazu Kent Beck: »for each desired change, make the change easy (warning: this may be hard), then make the easy change«
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.