EntityFramework: CodeFirst vs. ModelFirst

  • WPF

Es gibt 55 Antworten in diesem Thema. Der letzte Beitrag () ist von Mono.

    EntityFramework: CodeFirst vs. ModelFirst

    Hier wollen @Nofear23m und ich uns mit Datenbänkerei mittels EF und Wpf beschäftigen.
    Ich fang ma gleich an und stelle meine kleine "Bestellungen"-Anwendung rein, die ich gebastelt habe, um CRUD und Funktionalität von m:n-Relationen zu testen.

    Aber bevor du - @Nofear23m da jetzt ein Gegenstück zu entwirfst, müssen wir uns ühaupt auf ein konkretes Datenbank-Projekt einigen.
    Weil sonst basteln wir da Sachen, die überhaupt gar keine gegenseitigen Entsprechungen sind, sondern komplett unvergleichbar.
    Mir - und ich glaube sagen zu können: "uns" gehts aber um eine Gegenüberstellung der beiden Ansätze: ModelFirst und CodeFirst.

    Das mit dem auf ein Projekt einigen geht sogar ins Philosophische - müssen wir auch drüber reden, und eine Einigung finden.
    Etwa sagst du, der User soll aus einer Datenbank niemals etwas löschen dürfen.
    Ich finde, so pauschal kann man das nicht bringen. Sicherlich ist das oft sinnvoll in großen real-wirtschaftlichen Projekten, wo der User nicht der ProductOwner der Software ist, sondern die Software vom ProductOwner (etwa der Arbeitgeber des Entwicklers) kauft.
    Aber es gibt ja auch Hobbyprogrammierer, die sich ihr Sach zurechtbasteln wollen, das wäre ja absurd, sich da so einer komischen "Selbst-Bevormundung" zu unterwerfen.
    Und Datenbänkerei ist CRUD - alle 4: Create, Read, Update, Delete.

    Also mein Experiment-Ziel ist, die Möglichkeiten auszuloten, und da kann man nicht das D von CRUD von vornherein einfach wegstreichen.
    Weglassen kann man ja immer, aber zunächstmal will ich das komplette Programm.

    Ein weiteres Thema ist Validierung.
    Was ich eingestellt habe, gibt dazu bislang ühaupt nichts her. Also ich gehe davon aus, dasses nicht das endgültige Projekt ist, auf das wir uns einigen werden.
    Gibts noch weitere Busyness-Logik? - mir fällt grad nix ein.

    Was mir einfällt ist Thema Lokalisierung - weil da haben wir auf Arbeit einen Mords-Aufwand mit - wo ich immer denk, kann nicht wahr sein.

    Oder BenutzerRechte

    Oder MultiUser-fähigkeit

    Ah - der Unit-of-Work-Pattern - das könnte noch sehr interessant sein.

    aber die letzten 3 sollten wir bitte vertagen - mit CRUD, m:n und Validierung sind wir erstmal gut beschäftigt, ich wär derzeit dafür, das erstmal durchzuziehen.

    mein System
    Ach ich muss noch mein System sagen, das ist nämlich ziemlich altbacken:
    Also ich arbeite auf Win7, VisualStudio 2013 Community, Framework 4.5, EF6, kein Resharper, kein GitHub, kein Prism (Wpf-Framework), kein IOC-Container.
    Hat mich alles bislang nicht überzeugen können - ma sehn, vlt. wird ja auch davon was thematisiert.

    Zur Anwendung:

    Ich habe Mockdaten im Xaml-Designer, ich kann viele Daten generieren, und Laden und Speichern vonne Db.
    Ich kann alles editieren, löschen zufügen, sogar an den Bestellposten kannich via ComboboxColumn einstellen, dass ein anderer Artikel bestellt sein soll. Ist klar, für Bestellungen ist das Quatsch, aber prinzipiell sind Anwendungsfälle denkbar, wo genau sowas sinnvoll ist.
    Vielleicht machen wir ja ein Foto-Album - da wäre das als sinnvoll denkbar, nämlich um Fotos taggen zu können, und das Tagging auch bearbeiten.
    Kleine Besonderheit ist das Sql-Logging: Ich kann an und ausstellen, dass die generierten Sql-Scripte im Ausgabefenster mitgeschrieben werden.
    Ausstellen muss man das, wenn man Daten generiert hat, und dann abspeichert.
    Weil das sind > 1000 Datensätze, und wenn der jedes Insert-Command in die Ausgabe malt, läuft er auf einen Timeout.
    Ansonsten kann man den Log problemlos mitlaufen lassen.

    Jo, und jetzt bin ich erstmal gespannt, was alles beim Downloaden nicht funktioniert - mitte Portablität ist das ja meist nicht so einfach. 8-)



    Übrigens ist dieser Thread keine Privat-Veranstaltung für uns 2, sondern ist so öffentlich, wie öffentliche Threads in VbParadise-Foren numa sind. Also wer was dazu sagen oder fragen will - dazu ist das Forum da ...
    Dateien

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

    ErfinderDesRades schrieb:

    Aber bevor du - @Nofear23m da jetzt ein Gegenstück zu entwirfst, müssen wir uns ühaupt auf ein konkretes Datenbank-Projekt einigen.

    Sehe ich auch so.

    ErfinderDesRades schrieb:

    Aber es gibt ja auch Hobbyprogrammierer, die sich ihr Sach zurechtbasteln wollen, das wäre ja absurd, sich da so einer komischen "Selbst-Bevormundung" zu unterwerfen.

    So wie ich es in dem anderen Thread erstellt hatte kann man sich aussuchen für welche Models diese "Bevormundung" gelten soll. Es ist nämlich so das sich viele gar nicht bewusst sind was sie damit anrichten können wenn sie einen Datensatz aus einem relationellen Datensystem löschen. Hat ein Kunde vor Jahren einen Auftrag machen lassen kann ich den Kunden nicht löschen. Auch mit der löschweiterleitung ist das problem das hier dann evtl. der Auftrag mitgelöscht wird. Selbst wenn nicht. Ich lösche den Kunden und mache den Auftrag auf. Nu, es wird kein Kunde angezeigt. Was ist los? Schlecht. So gut wie jeder Datensatz ist irgendwie mit einem anderen verbunden. Zumindest wenn man seine DB zumindest in der zweiten normalisierungsform hat. Ergo ist löschen falsch. Und ja, es bleibt CRUD. Denn bei meinem Ansatz kann man weiterhin löschen. Nur wird INTERN der DS nur als gelöscht markiert.

    ErfinderDesRades schrieb:

    Ein weiteres Thema ist Validierung.

    Für die habe ich was für Models vorbereitet

    ErfinderDesRades schrieb:

    Was mir einfällt ist Thema Lokalisierung - weil da haben wir auf Arbeit einen Mords-Aufwand mit - wo ich immer denk, kann nicht wahr sein.

    Hier habe ich auch viel getestet und probiert. und bin hier geblieben. Sehr einfach und sehr schnell. Aktuell in einem sehr großen Projekt im Einsatz und läuft super.

    ErfinderDesRades schrieb:

    Vielleicht machen wir ja ein Foto-Album - da wäre das als sinnvoll denkbar, nämlich um Fotos taggen zu können, und das Tagging auch bearbeiten.

    Klingt gut. Schreibst du ein Lastenheft?

    PS: Lassen wir uns aber etwas Zeit, bin im Moment ein wenig eingespannt.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:


    So wie ich es in dem anderen Thread erstellt hatte kann man sich aussuchen für welche Models diese "Bevormundung" gelten soll. Es ist nämlich so das sich viele gar nicht bewusst sind was sie damit anrichten können wenn sie einen Datensatz aus einem relationellen Datensystem löschen. Hat ein Kunde vor Jahren einen Auftrag machen lassen kann ich den Kunden nicht löschen. Auch mit der löschweiterleitung ist das problem das hier dann evtl. der Auftrag mitgelöscht wird. Selbst wenn nicht. Ich lösche den Kunden und mache den Auftrag auf. Nu, es wird kein Kunde angezeigt. Was ist los? Schlecht. So gut wie jeder Datensatz ist irgendwie mit einem anderen verbunden. Zumindest wenn man seine DB zumindest in der zweiten normalisierungsform hat. Ergo ist löschen falsch. Und ja, es bleibt CRUD. Denn bei meinem Ansatz kann man weiterhin löschen. Nur wird INTERN der DS nur als gelöscht markiert.


    Abgeschlossene Aufträge gehören nach der Tagesendeverarbeitung gelöscht, zumindest aus der Auftragsverwaltung. Allerdings gehören sie ins Archiv eingetragen. Das muss so geschehen, dass eine Rechnung auch nach Jahrenn völlig identisch zum Original als Duplikat gedruckt werden kann, also mit Kopien der zum Zeitpunkt der Erstellung der Rechnung gültigen Daten (Kundenname, Adresse, Währung, Beträge, UstSteuer und -Sätze, etc.). Schlimmstenfalls muss ein Beleg mit alles Zusatzfristen 13 Jahre (10 plus weitere Fristen) dem Wirtschaftspürfer vorgelegt werden können.
    Es ist im Archivsystem immer alles Vorhanden was zur Rechnung auch je benötigt wurde, nicht etwa als Zeiger auf eine andere Tabelle. Ich weiß, dass das der üblichen Datenbänkerei widerspricht, aber so ist es nun einmal.

    Anonsten ist es immer sinnvoll bei Kundendaten statt wirklich zu löschen lediglich "löschmarkieren" zu verwenden. Das kann der Anwender aber ruhig wissen und somit sollte man es auch nicht löschen nennen.
    Sollen Datensätze wirklich (tiefen-)gelöscht werden, dann macht man das von entsprechenden Rechten (Gruppe Administratoren, Gruppe Finanzleiter, etc. abhängig).
    Aus dem Archivsystem kann und dürfren die Daten nicht gelöscht werden, jedenfalls nicht vom Anwender egal welcher Rechtegruppe er angehört.
    Das mit dem Auftrag war ein Beispiel, vieleicht ein Blöd gewähltes, aber naja. Ich denke wir sind da auf einer Welle.
    Ob man es nun löschen nennt oder löschmarkieren kann man im jeweiligen View entscheiden. Ich würde z.b. nie einen Benutzer (weil es z.b. Kündigt) löschen. Er wird löschmarkiert, alle Protokolle usw. bleiben somit erhalten.

    Und genau sowas sollte man "neulingen" vermitteln. Nämlich das sie sich ganz sicher sein müssen was sie evtl. löschen und was dieses löschen bewirken kann.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Trennt euch einmal vom Geschäftswesen, wo aus derlei gesetzlichen Vorgaben, das gänzliche Löschen von Daten daraus nicht zulässig ist...
    Es gibt ja auch andere Beispiele zu Anwendungen, wo das Löschen ermöglicht wird, weil sonst dort abgelaufene Daten nur die Datenhaltung unnötig aufbläht.
    *) irgendwelche Ergebnislisten von Spielen, wo es nicht hoch offiziell hergeht...
    *) oder ein Schichtplan für einen Vorgesetzten, der seine Mitarbeiter damit verplant und die Verplanung nach einer abgelaufenen Woche wieder entfernen will, weil's keinen mehr interessiert...
    *) uvm.

    VB1963 schrieb:

    Trennt euch einmal vom Geschäftswesen, wo aus derlei gesetzlichen Vorgaben, das gänzliche Löschen von Daten daraus nicht zulässig ist...
    Jo - und ist glaub nichtmal wirklich wahr.
    Bei uns auf Arbeit ist von Datenschutz die Rede, und da scheints Gesetze zu geben, dass nach etlichen Jahren gewisse GeschäftsProzesse rückstandslos gelöscht werden müssen - auch aus Archiven.

    Aber ich hab den halben Vortrag verschlafen - sowas von langweilig, und auch total gesponnen. Also die Gesetze haben scheints Leute gemacht, die durch technische Bedingtheiten nicht weiter belastet sind...

    Und wenn ich bedenke, was jedes Handy an persölichen Daten ins Internet streut (und damit nach Amerika, Russland, England und Katar schickt) kommen mir diese Datenschutz-Amok-Läufe iwie grotesk lächerlich vor.
    Da brennt das Haus ab, und man kümmert sich, dass der Kanarienvogel auch Jod-S-11-Körnchen kriegt.
    Deutschland - Verordnungs-Weltmeister.

    Nofear23m schrieb:

    Hallo

    Ich hatte nun Zeit mit Gedanken dazu zu machen.
    Da wir auf den Unterschied CodeFirst VS ModelFirst eingehen wollen ist es ja unerheblich WAS gemacht wird. Wie wollen ja nur den Unterschied zwischen den beiden Varianten der Model-Generierung eingehen.
    Hier ist ja der einzige Unterschied (im groben) wie das Model erstellt wird. Also über T4 mit dem Designer oder das man die Klassen und Props tippt.

    Ich würde also eher auf spezielle in der Praxis auftauchende Probleme eingehen. Einige hast du ja bereits angesprochen. Ich stelle mal welche in den Raum, du kannst ja ergenzen.

    N:M Relations
    Validierung
    Lokalisierung von DB-Werten
    Basisklassen (IsDeleted, CreatedOn, CreatedAt, LastEditedOn, LastEditedAt)
    Konflikterkennung
    Automatisiertes Audit-Logging

    Hier kann man ja jeweils schreiben wie man es bei ModelFirst machen, und als vergleich wie man es in CodeFirst macht.

    Anfangen würde ich aber damit die wesentlichen Unterschiede der beiden Methode inkl. Performancemessungen aufzuzeigen!! Soll ich das vorbereiten?
    Jo - ich hab auch paar Gedanken - nur zum Foto-Archiv noch nicht.
    Etwa könntest du doch ganz einfach meine Vorlage 1:1 mit CodeFirst umsetzen - ohne Viewmodel und pipapo.
    Das sollte kein Aufwand sein, und hätte man schoma eine Vergleichbarkeit.
    In einem weiteren Schritt ein Viewmodel dranbasteln - dann hätte man die nächste Vergleichbarkeit, und das wäre glaub interessanter.
    Allerdings ist der Vergleich etwas unfair, weil die Anwendung leistet (noch) nichts von dem, was zu leisten von eim Viewmodel zu unterstützen wäre.
    Dein Viewmodel wird also imo relativ schlecht abschneiden, nämlich als "überflüssiger Kropf".
    Weil es geht ja erwiesenermassen auch ohne.
    Aber das kann man ja einbeziehen in die Betrachtung.

    Der nächste Vorwärts-Schritt ginge dann von dir aus, dass du die Anwendung erweiterst (oder eine neue anfängst (etwa das Fotoalbum)), um Features, bei denen dann dein Viewmodel auch tatsächlich mal was zu tun bekommt.
    Und dann bin ich dran, zu versuchen, das nachzubasteln und zu versuchen, es gleichwertig, aber hofflich mit einfacheren Mitteln umzusetzen.
    Aber dazu lass uns die Features erst noch besprechen, weil das kann ja auch unfair werden, oder auch nur überaus aufwendig, wenn du da gleich alles auf einmal mit reinpackst.
    Jdfs. hätte man dann zusätzlich zur Vergleichbarkeit Mode-/Code-First auch eine Vergleichbarkeit verschiedener Auffassungen von MVVM.

    Anfangen würde ich aber damit die wesentlichen Unterschiede der beiden Methode [Code-/Model-First] inkl. Performancemessungen aufzuzeigen!! Soll ich das vorbereiten?
    Ja gern - das ist ja meine Intention (an Performance habich dabei aber garnet gedacht).
    Aber wie gesagt: dazu müsstest du mein Werk erstmal nachbasteln.
    @ErfinderDesRades. Ich würde ja dein Projekt in CodeFirst umbauen. Habe hier allerdings mehrere Probleme.

    1.) Das Projekt startet zwar abr es geht kein Fenster auf, sonst tut sich aber auch nix. Wie wenn er in einer Endlosschleife hängen würde. (Auf 3 Rechnern getestet, in der Arbeit meldet sich auch Symantec)
    2.) Die Unterschiede zwischen Model-First und Code-First zeigen sich besser in einer Consolenanwendung da die Unterschiedlichen herangehensweisen ja nichts mit WPF zu tun haben.
    3.) Du Implementierst InotifyPropertyChanged in dein T4 Template. Das baue ich nicht nach. Warum habe ich bereits erklärt.

    Für mich stellt sich in erster Linie jetzt die Frage, willst du CodeFirst mit ModelFirst vergleichen oder willst du "nur" ein T4 Template erstellen welches Tipparbeit spart.
    Bei letzterem bin ich definitiv raus sobald etwas von einem VM mit einem T4 generiert wird. Mich stört ja schon das INotifyPropertyChanged enthalten ist. Es ist jetzt kein Fehler, kann man machen, stört mich aber weil damit vermittelt wird das man keine Trennung benötigt und direkt an die Model-Klassen Binden kann, was eine ganz schlechte Idee ist da man sich viele Probleme einhandeln kann.

    Erst recht wenn man in der WPF mit MVVM Arbeitet. Hier beschreibt das Pattern die Trennung zwischen Model und ViewModel. Im Idealfall muss hier die View auch nichts vom Model wissen da sich dieses ändern kann.

    Wir sollten klären WIE wir die beiden - Ich nenne es jetzt mal "Model-Erstellarten" vergleichen. Denn dies beschreibt der Titel, nicht mehr, nicht weniger!

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    1) Sowas habich befürchtet. Hoffentlich kriege ich das noch iwie gefixt. Sowas ist lausig zu fixen, weil bei mir funztes ja.
    2) MIt Consolen-Anwendungen kann ich garnix anfangen. Etwa ein Knackpunkt ist ja die m:n - Relation, und damit kann man erreichen, per ComboboxDatagridColumn einen Bestellposten auf einen anderen Artikel umzustellen. Wie gesagt ist bei Bestellungen eiglich nicht erwünscht, aber mir gehts um die technische Möglichkeit.
    Diese Useability ist in Console ja garnet nachzubilden - Databinding gibts da ja garnet.
    3) naja, für "quick & dirty" könnteste da vlt. doch mal über Schatten springen. Man hätte dann 2 sehr ähnliche Lösungen, und eben genau die Vergleichbarkeit von Code-/Model-First. Du sagst ja selbst: hat mit MVVM nix zu tun.
    Ansonsten kannste natürlich auch "ordentlich" in deinem Sinne programmieren - dann hat man zusätzlich die Vergleichbarkeit von "sauberem" MVVM zum meim "Anarcho-" MVVM.
    Das ist jedenfalls ein ganz wesentlicher Punkt, dass ich mal nicht immer nur die nachgebeteten Pattern vorgesetzt bekomme, sondern dass man mir konkret aufzeigt: "Guck - das kriegst du mit deim Anarcho-Ansatz nicht hin, und deswegen beten alle die Pattern nach."
    Also mir wäre lieber, die beiden Vergleiche voneinander getrennt zu halten, aber wenns dir gar zuwider ist, machste halt "sauberes" MVVM, und man muss mit einem quasi "zusammengemanschten" Vergleich zurechtkommen.
    Jo - ist eiglich halb so wild - die CodeFirst-Version kann ich ja auch selbst liefern - will ich ja eh mal probieren.

    Nofear23m schrieb:

    Ich nenne es jetzt mal "Model-Erstellarten" vergleichen. Denn dies beschreibt der Titel, nicht mehr, nicht weniger!
    Ja, der Thread-Titel ist ziemlich schlecht - ich bin ebenso oder sogar mehr dran interessiert, unsere unterschiedlichen Auffassungen von MVVM zu vergleichen.

    ErfinderDesRades schrieb:

    Diese Useability ist in Console ja garnet nachzubilden - Databinding gibts da ja garnet.

    Es geht ja beim vergleich ModelFirst VS CodeFirst auch nicht um DataBinding.

    ErfinderDesRades schrieb:

    Ja, der Thread-Titel ist ziemlich schlecht - ich bin ebenso oder sogar mehr dran interessiert, unsere unterschiedlichen Auffassungen von MVVM zu vergleichen.

    Naja, das wäre aber ein anderes Thema. Hier gehts ja um EntityFramework und das hat mit WPF und/oder MVVM nix zu tun. Mir ist in einer MVVM Anwendung schnuppe wo die Daten herkommen und wie, darum kümmert sich ein DataAccessLayer oder die Businesslogik. Gehört nicht hier her.

    Ich mache heute Abend ein Beispiel (mit dem nötigsten) inkl. einem m:n Beispiel.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

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

    Ich hätte da mal ein paar Fragen Anmerkungen
    1. Warum nur Code First und Model First? Was ist mit Database First?
    2. In EF Core gibt es, so wie ich das lese, kein Model First
    3. Eine Konsolenanwendung oder eine API sehe ich ebenfalls als geeigneter an.
    Die deutsche Sprache ist Freeware, du kannst sie benutzen, ohne dafür zu bezahlen. Sie ist aber nicht Open Source, also darfst du sie nicht verändern, wie es dir gerade passt.
    Hallo @MrTrebron

    Zu 1: Weil ErfinderDesRaden dies wollte. Er möchte vergleichen, vermutlich weil ich meinte das CodeFirst der intuitivere Ansatz ist und ModelFirst sowie DatabaseFirst nie so richtig funktionierte. Siehe Antwort 2
    Zu 2: Richtig, ohne den PowerTools sind die anderen beiden Ansätze nicht mehr von MS vorgesehen, was seinen Grund hat, erstens mussten immer alle drei Ansätze implementiert werden und zum zweiten fallen nun sehr viele Sachen weg wie Proxyerstellung, T4, edmx Modelerstelung usw.
    Zu 3: Sehe ich auch so, da kann man sich auch was den code betrifft auf das wesentliche konzentrieren.

    Grüße :P
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo

    Ich habe mal ein Projekt erstellt mit einer Konsole.
    Da hier die Projekte vermutlich hin und her geschoben werden wie wild und ich das Forum (oder besser deren Server) jetzt nicht zumüllen will dachte ich "machste ein Git Repository" auf VS Team Services.
    Jeder der ein MS Konto hat, und das hat ja jeder der VS hat, kann eingeladen werden und mitwirken bzw. testen.

    @ErfinderDesRades jetzt könntest du einfach deine Projekt mit rein packen und wir können schön vergleichen wenn es dir recht ist, gerne wenn du willst auch mit UI wenn dir das lieber ist, im Grunde geht es aber nur um den vergleich.


    Einfach PN mit dem MS Konto (Mailadresse) an mich und ich füge den jenigen zum Repository hinzu.
    patschka.visualstudio.com/EF_CodeFirstVsModelFirst/_home


    Beschreibung meines Projekts:
    CodeFirst Ansatz wo eine DB gelöscht und erstellt werden kann. Ich habe mir ein BLOG ausgesucht da dies leicht von jedem nachvollzogen werden kann.
    Es gibt einen Blog mit X Posts. Jeder Post wird von eine User gepostet, in jedem Post können X User markiert werden. Jeder USer kann in X Posts markiert sein.

    Datenbankmigration wird automatisch durchgeführt! Wird ein Property hinzugefügt z.b. beim User vieleicht die Schuhgröße, oder eine Klasse (somit eine Tabelle) hinzugefügt wird beim nächsten Start zur Laufzeit die DB Migriert. Dies bewerkstelligt die Klasse Configuration welche von DbMigrationsConfiguration erbt.

    Es gibt eine Model-Basisklasse welche gewisse Properties zu Verfügung stellt:

    VB.NET-Quellcode

    1. Public Class ModelBase
    2. Public Overridable Property CreatedBy As String = Environment.UserName
    3. Public Overridable Property CreatedOn As String = Environment.MachineName
    4. Public Overridable Property LastUpdateBy As String = Environment.UserName
    5. Public Overridable Property LastUpdateOn As String = Environment.MachineName
    6. <Timestamp>
    7. Public Overridable Property RowVersion As Byte()
    8. End Class


    Jede Modelklasse verfügt somit wenn sie von dieser Klasse erbt über diese Eigenschaften. Inkl. der RowVersion um z.b. auf Konflikte reagieren zu können.

    Weiters habe ich zwei Interfaces implementiert um gewisse funktionalitäten in die ganze Sache zu bekommen.
    z.b. schutz vor unabsichtlichen Löschvorgängen welche für gewisse Klassen nicht erlaubt sind.

    ILogicalDelete schreibt zwei Propertys vor. DeletedFlag und DeletedTimestamp. Ich denke die sind selbsterklärend. Jeder Model-Klasse welche dieses Interface implementiert bekommt diese Eigenschaften und kann somit NICHT gelöscht werden. Nur als gelöscht markiert, warum erkläre ich weiter unten.
    ILogicalTimestamp schreibt auch zwei Properties vor. LastUpdateTimestamp und CreationTimestamp. Auch selbsterklärend, wie diese befüllt werden erkläre ich gleich. Der hintergrund ist wie folgt. Ich will ja nicht immer bei jeder änderung eine Datensatzes daran denken müssen immer brav die Zeit hier einzutragen, das wird uns der EF Kontekt übernehmen da er durch das Interface weis welche Klasse diese Eigenschaften hat und welche nicht.

    Also hier die von mir überschriebene SaveChanged Methode des EF DB Kontexts:

    VB.NET-Quellcode

    1. Public Overrides Function SaveChanges() As Integer
    2. Dim objectStateEntries = ChangeTracker.Entries().Where(Function(e) TypeOf e.Entity Is ModelBase AndAlso e.State <> EntityState.Detached AndAlso e.State <> EntityState.Unchanged).ToList()
    3. For Each _Entry In objectStateEntries
    4. Dim entityBase = TryCast(_Entry.Entity, ModelBase)
    5. If entityBase Is Nothing Then Continue For
    6. Select Case _Entry.State
    7. Case EntityState.Deleted
    8. Dim logicalDelete = TryCast(entityBase, ILogicalDelete)
    9. If (logicalDelete IsNot Nothing) Then
    10. _Entry.State = EntityState.Modified
    11. logicalDelete.DeletedTimestamp = DateTime.Now
    12. logicalDelete.DeletedFlag = True
    13. End If
    14. Case EntityState.Modified
    15. Dim logicalTimestamp = TryCast(entityBase, ILogicalTimestamp)
    16. If (logicalTimestamp IsNot Nothing) Then
    17. logicalTimestamp.LastUpdateTimestamp = DateTime.Now
    18. End If
    19. Case EntityState.Added
    20. Dim logicalTimestamp = TryCast(entityBase, ILogicalTimestamp)
    21. If (logicalTimestamp IsNot Nothing) Then
    22. logicalTimestamp.CreationTimestamp = DateTime.Now
    23. logicalTimestamp.LastUpdateTimestamp = DateTime.Now
    24. End If
    25. End Select
    26. Next
    27. Return MyBase.SaveChanges()
    28. End Function


    Es werden erstmal alle Entitäten genommen welche geändert, hinzugeügt oder gelöscht wurden.
    Ist eine Entität gelöscht worden wird nachgesehen ob diese das ILogicalDelete Interface implementiert, wenn ja wird der EntityState von Deleted auf Modified gesetzt. Somit ist diese in der DB nicht mehr gelöscht sondern nur als gelöscht markiert.
    Wurde eine Entität geändert, wird der LastUpdateTimestamp gesetzt wenn die Klasse das Interface ILogicalTimestamp implementiert, ich muss mich also nicht darum kümmern.
    Wurde eine Entität hinzugefügt wir auch noch der CreationTimestamp gesetzt solange die Klasse das ILogicalTimestamp implementiert hat.


    Ich hoffe mein vorgehen ist im Sinne von @ErfinderDesRades und hoffe das es hier keine "Konflikte" gibt weil ich eine Quellcodeverwaltung verwende, ich finde es ist einfach viel besser als hier Projekte hin und her zu schaufeln.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    1.) Das Projekt startet zwar abr es geht kein Fenster auf, sonst tut sich aber auch nix. Wie wenn er in einer Endlosschleife hängen würde. (Auf 3 Rechnern getestet, in der Arbeit meldet sich auch Symantec)

    Ich habe hier das gleiche Probleme. Beim Stepwise-Debugging bleibt er bei mir in folgender Zeile hängen (Mainmodel.vb):

    VB.NET-Quellcode

    1. Private Sub New()
    2. Commands("").AddFlow(AddressOf GenerateData)(AddressOf Reload)(AddressOf Save, AddressOf CanSave)("Log Sql")(AddressOf Test).Nop() ' .Nop(): Flow-Indexer erzwingen eine Auswertung
    3. If IsInDesignMode Then GenerateData() : Return
    4. _Context = New BestellungenEdmContainer
    5. AddHandler Commands("3").CheckedChanged, Sub(s, e) SetLogSql()
    6. Commands("3").SetChecked(True)
    7. Dbg("Database new created: {}".FormatX(_Context.Database.CreateIfNotExists)) '<--- Hier ist der Überltäter
    8. End Sub

    Kommentiere ich die Zeile aus, so startet bei mir zumindest das Fenster.

    Die tiefergehende Fehleranalyse überlasse ich den Profis ;)

    Übrigens, sehr spannend dies zu verfolgen, auch wenn meine Programmierkenntnis in diesem Bereich gegen Null geht.
    Aber vielleicht auch gerade deswegen umso spannender, eben weil ich mit diesem Bereich noch keinerlei Berührungspunkte hatte.
    Habe das Problem auf nem Firma-Rechner glaub reproduzieren können, und auch eine Abweichung in der ConnectionString.DataSource - Angabe gefunden.
    Und die jetzt umgedichtet, wie's im NoFear-Upload-ConnectionString notiert ist - zumindest der Firma-Rechner ist damit zufrieden.

    Update in post#1

    Ists jetzt gefixt?

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

    Nofear23m schrieb:

    Einfach PN mit dem MS Konto (Mailadresse) an mich und ich füge den jenigen zum Repository hinzu.
    Kannste das Github nicht so einrichten, dasss man deine Solution da normal downloaden kann?
    Ich mag mich da nicht einloggen, wenn ich in NoScript angucke, welche Sites da alles mit-drinrumschnüffeln wird mir nicht unübel.
    Vor allem widerspricht das doch dem öffentlichen Charakter des Forums, wenn nur durch dich autorisierte Leute das downloaden können, wovon hier die Rede ist.

    ErfinderDesRades schrieb:

    Vor allem widerspricht das doch dem öffentlichen Charakter des Forums, wenn nur durch dich autorisierte Leute das downloaden können, wovon hier die Rede ist.

    Am ende wird es einen Anhang geben, aber bis dahin ist es doch unnötig oder?
    Na wenn du nicht willst schlage was anderes vor, ich finde es für eine gute idee.

    ErfinderDesRades schrieb:

    welche Sites da alles mit-drinrumschnüffeln wird mir nicht unübel.

    Leicht paranoid?

    Egal, ich habe ehrlich gesagt keine Lust hier Anhänge hin und her zu schicken und das Forum wegen sowas zumüllen zu müssen wenn es unnötig ist. Gerne sende ich es dir anders und du stellst es auf Github oder so, ICH arbeite meist mit Team Foundation, das funzt wenigstens.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

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

    Geht leider bei TFS nicht. Aber ich habe Trebton gefragt. Es wirds Online stellen. Komisch, habe schon einige Leute eigeladen weil sie angefragt haben, hatte niemand probleme. Aber mal sehen. Ich stehe hald mit GitHub auf dem Kriegfuß, ist mir zu unflexibel.

    Also mal abwarten ok.
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    So, wie besprochen hier der Link zu github

    https://github.com/MrTrebron/vbp_EF_CodeFirstVsModelFirst


    Nachtrag: Anonymer Download wurde ebenfalls getestet

    Und noch ein Nachtrag: Projekt kompiliert und läuft. VS 2017 Community Version 15.5.2
    Die deutsche Sprache ist Freeware, du kannst sie benutzen, ohne dafür zu bezahlen. Sie ist aber nicht Open Source, also darfst du sie nicht verändern, wie es dir gerade passt.

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