Bindung nach Entity Model first aktualisiert Daten nicht!

  • WPF

Es gibt 118 Antworten in diesem Thema. Der letzte Beitrag () ist von Jeiss.

    Nofear23m schrieb:

    Du weist ja, ich mag klickiBunti Designer nicht.
    Und ich mag "Repeat Yourself" nicht.
    Daher habich einen CollectionChanged-Handler gebastelt, an den man jetzt alle ListCollectionViews hängen kann:

    VB.NET-Quellcode

    1. Public Sub New()
    2. '...
    3. UrgentOrdersView = New ListCollectionView(UrgentOrderList)
    4. AddHandler DirectCast(UrgentOrdersView, ICollectionView).CollectionChanged, AddressOf CollectionChanged
    5. End Sub
    6. Private Sub CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
    7. Select Case e.Action
    8. Case NotifyCollectionChangedAction.Add
    9. Dim itm = e.NewItems(0)
    10. Dim tp = itm.GetType
    11. If Not tp.IsVisible Then Return
    12. Dim dbSet = _context.Set(tp)
    13. dbSet.Add(itm)
    14. Case NotifyCollectionChangedAction.Remove
    15. Dim itm = e.OldItems(0)
    16. Dim tp = itm.GetType
    17. If Not tp.IsVisible Then Return
    18. Dim dbSet = _context.Set(tp)
    19. dbSet.Remove(itm)
    20. End Select
    21. End Sub

    ErfinderDesRades schrieb:

    Daher habich einen CollectionChanged-Handler gebastelt, an den man jetzt alle ListCollectionViews hängen kann:

    Sicher sinnvoll. In der Praxis später wohl nicht wirklich interessant. Ich muss ja das Model auch Validieren usw.
    hier muss ich dann wieder Casten und versuchen die Objekte zu validieren. Ich persönlich finde es nicht weiter tragisch wenn ich 2 Zeilen mehrmals schreibe.
    So ist er übersichtlicher und ich kann gezielt auf diverse Fälle reagieren. Beispielsweise muss ich bei Add noch Properties setzen welche im DataGrid nicht vorhanden.

    Ich z.b. habe immer eine Art ChangeLog in der Model Basisklasse. Wo ich in Spalten wie LastChangeBy und LastChangeAt setze. Das kann ich hier schlön machen.
    Auch kann ich einen Auditlog schreiben usw. Das kann man auch alles in die ContextKlasse packen indem man SaveChanges überschreibt, aber bei ModelFirst mit einem T4 wird das wohl sehr schwierig.

    Aber sicher nicht schlecht wenn man alle CollectionViews drannhängen kann. Finde hat auch was, in gewissen Fällen hald.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Ja ich darf nicht vergessen deine letzte Antwort als "Hilfreich" zu klicken.
    ​Du hast viele Verbesserungen vorgenommen. Das Language Property war mir nicht aufgefallen, hab ich so noch nie gesehen.
    ​Da hab ich viel zu "entdecken".

    ​Eins ist mir jetzt klar, mein UrgentOrders Projekt wird auf jeden Fall ein MVVM Projekt werden. Noch vor deiner Antwort war mir klar, dass ich auf deinen Vorschlag (etwas weiter oben, Antwort/Beitrag N°31) zurückgreifen würde.
    "Richtiger MVVM Aufbau"​ ist doch ein sehr schöner Titel für ein neues Thema, finde ich auch.... ;)
    ​Und als Vorbereitung werde ich mir die letzten Verbesserungsvorschläge, die hauptsächlich du und ErfinderDesRades, mir während der zwei letzten Wochen gepostet habt.
    ​Anders als bei Google sind die wenigstens (wie sagt man das) "zusammenhängend", damit meine ich, dass alles so gemacht ist, dass es einem und dem selben Zweck dient. Ohne murksen und ohne Umwege. (Umwege gehe ich immer dann, wenn ich etwas nicht kann... und da kann ich ja jetzt im Forum nachfragen)

    Danke,
    ​Jeiss

    Nofear23m schrieb:

    Ich persönlich finde es nicht weiter tragisch wenn ich 2 Zeilen mehrmals schreibe.
    ähm - es sind 15 Zeilen - mindestens.
    Bei 10 Entitäten sieht das schon sehr schnell aus wie KrautnRüben, und ich würd die Datei nicht mehr angugge mögen - 150-200 Zeilen BoilerPlate <X .
    Mal abgesehen von den Copy&Paste-Fehlern, die man bei Self-Repeating immer so gerne einbaut.

    Und validieren, loggen,... erstma abwarten.
    Damit beschäftige ich mich, wenn gebraucht wird.

    ErfinderDesRades schrieb:

    Bei 10 Entitäten sieht das schon sehr schnell aus wie KrautnRüben


    Nenene. Moment. Du Verstehst da jetzt was falsch. Bitte sehe jetzt nicht nur dieses schnelle Fallbeispiel.
    In einer Praxisorientierten Lösung Arbeitet man ja gar nicht mit den Entitäten!
    Du hättest ja immer ein ViewModel drumrum. Und hier gebe ein dann keine ObservableCollection(of Answer) sondern eine ObservableCollection(of AnswerVM).
    Bitte häng dich nicht auf dem Beispiel auf. Das dient nur zum Beispiel wie man in EF speichert.

    Mal abgesehen davon das wenn ich 10 DataGrids auf nem Window habe ich sowieso ein Designproblem habe will ich ja selbten die Modelklassen in einem View so abbilden wie diese sind. Ich benötige also ein ViewModel.
    Das ViewModel stellt mir die Propertys zur verfügung welche der User zur Eingabe benötigt, nicht weniger, nicht mehr. Dieser kümmert sich dann darum das die Daten RICHTIG in das Model gelangen und gespeichert wird.

    Denk mal drüber nach, ich schweife jetzt nicht mehr aus und überlasse es deiner Fantasie. Wie gesagt, gerne mache ich ein Beispiel.
    Aber so wie du das jetzt gaubst funzt das nicht lange. *probiers*

    Ausserdem und das meine ich jetzt mit vollen ernst, empfielt es sich das des ViewModel vom EF gar nichts weis, also gar keinen Verweis auf das EF und den Context hat sondern nur auf das Model!!!
    Und das ist es was ich meine mit "richtiger aufbau.

    Nur so bleibe ich flexibel und kann jederzeit wenn nötig auf eine andere EF Version, einen anderen OR Mapper oder etwas anderes. Kommt hald immer drauf an wie weit man es treiben will und wie sehr die einzelnen Layer austauschbar sein sollen.

    Edit: @Jeiss

    Jeiss schrieb:

    Es werden keine neuen Answers im Answers_DataGrid mehr angenommen.

    Ja, im neuesten Beispiel nicht, das wollte ich dir überlassen dies zu implementieren. Nur so lernst du wie das ganze funktioniert. Du hast mit der UrgentOrderList ein Beispiel wie es geht, versuche dies zu implementieren das der Context dies mitbekommt und der neue Eintrag im Context landet.

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

    Nofear23m schrieb:

    Nenene. Moment. Du Verstehst da jetzt was falsch. Bitte sehe jetzt nicht nur dieses schnelle Fallbeispiel.
    In einer Praxisorientierten Lösung Arbeitet man ja gar nicht mit den Entitäten!
    Du hättest ja immer ein ViewModel drumrum.
    Naja ma abwarten, die praxisorientierte Lösung.
    gut möglich, dass wir da nicht einer Meinung sind.
    Vor allem: Mit "Entität" meine ich nicht konkret die generierten Objekte, sondern überhaupt alles, was als Klasse designed ist, um etwas zu modellieren - sei es Model oder Viewmodel, generiert oder selbstgebastelt.
    Nee - Entität ist ein noch abstrakterer Begriff: Entität ist, was aus der Realität als Klasse ins Datenmodell zu übertragen ist - hurra - ich habs endlich geschafft, "Entität" zu definieren, wie ichs meine. :thumbsup:

    ErfinderDesRades schrieb:

    gut möglich, dass wir da nicht einer Meinung sind.

    Gut möglich. Aber es ist nun mal so das man nie direkt auf Properties vom Model bindet sondern auf Properties des ViewModels.
    Grund? Ganz einfach, sie führen kein OnNotifiPropertyChanged durch. Also spätestens im DetailView hast du ein problem. Klar.... T4 editieren usw. super.

    ErfinderDesRades schrieb:

    Vor allem: Mit "Entität" meine ich nicht konkret die generierten Objekte, sondern überhaupt alles

    Ich weis, bitte lass uns nicht wieder diese Diskussion führen, wird echt wieder OffTopic. Sobal EF im Spiel ist sollte man aufpassen was man Enität nennt, da in EF entitäten nun mal ModelInstanzen sind. Is so, hab ich mir nicht ausgedacht.
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    Nofear23m schrieb:

    Is so, hab ich mir nicht ausgedacht.
    Isses nicht: de.wikipedia.org/wiki/Entit%C3%A4t_(Informatik)
    Ich würde das englische Wort "Entity", okkupiert durch MS's Verwendung, auch nicht gleichsetzen wollen mit dem deutschen Wort "Entität".

    Also eine Entity ist mw eine Modell-Instanz, wenn man mit EF arbeitet - aber das ist keine Entität im Sinne der Informatik.
    Das muss jetzt sein oder?

    Hier gut zu sehen.
    Achja, LinqToEntities wurde fürs EntityFramework entwickelt. :/

    Bitte lassen wir das. ICH werde sobald EF im spiel ist genau drauf schaun WAS ich eine Entität nenne und was nicht. Ein ViewModel sichern nicht. Das ist ein ViewModel und bleibt eines. Und es ist eine Klasse, eine ViewModel-Klasse.
    Eine Klasse im EF Model ist eine Model-Klasse. Und ein ergebniss einer EF Abfrage ist eine Entität. Aber jeder wie er will. Aus, Fertig. Lassen wir das bitte.

    Willst du wirklich den Threadsteller so verwirren nur damit du meinst das dein "Wort" jetzt das Wort ist was hier hin gehört. Mach es Ihm doch nicht so schwer. Ist schon ein wenig Egoistisch oder? Fühl dich jetzt bitte nicht angegriffen, ich versuche immer es für den Fragesteller so einfach wie möglich zu halten, was diese Diskussion nicht macht. Wenn ich mit EF Arbeite und im Netz suche ist immer von Entitäten die Rede, das bringt den Fragesteller hier jetrzt total durcheinander wenn er im Bezug auch ViewModel-Klassen was von Entitäten liest. Why? Damit du recht hast, ja hast du. Ich gebe dir recht, habe ich die ganze Zeit. Ich weis auch was Entitäten sind, nehme allerdings abstand von dem Wort sobald EF im spiel ist. Damit jemand der sich nicht so gut auskennt auch mit den Wörtern klar kommt und was damit anfangen kann.

    Bitte Eckard lassen wir das, du hast recht.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Hab noch immer nix gefunden. Hab, die mir selbst gegebene Zeit, für die Lösung des Problems längst überschritten.
    ​Hab sogar vergessen was zu essen... :|

    ​Was mir einleuchtet, ist dass die Eigenschaft "ShownAnswers" an die ja das AnswresGrid gebunden ist immer (bei jedem ListView_CurrentChanged aus dem context mit den "ursprünglichen/anfänglichen" answers lädt. Kann ja so nie was neues hinzukommen. Aber diese Einsicht löst die Aufgabe nicht!

    ​Wenn ich irgend etwas "raten" müsste bevor ich endlich mal etwas essen gehe Würde ich sagen es müsste eine separate "AnswersView" her. Die müsste auch ein "CollectionChanged-Event" bekommen. In der Prozedur müsste der Context die neuen oder geänderten "AnswerEigentschaften" zugewiesen bekommen.
    ​Das "AnswerGrid" müsste an diese "AnswersView" gebunden werden.

    ​Ok, ich hoffe zwar, dass ihr wegen meiner Antwort jetzt keinen Herzinfarkt macht, aber ich gehe jetzt erst mal etwas essen.

    Bis bald,
    Jeiss
    Hallo

    Richtig. Du schlagst den richtigen Weg ein. Eine CollectionView auch für die Answers und genauso das CollectionChanged behandeln wie bein den UrgendOrders. Wenn ein DS hinzugefügt wird fürgst du das neue Objekt dem Context hinzu. Ab da wird der Context dieses Objekt auch mit persistieren.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Hallo da draussen in der weiten Welt..Guten Tag.

    Nee, ich gebs auf... will mir nicht noch einen Tag versauen ohne dass was raus kommt.

    Hab zwei neue Properties eingebaut. Sehen wie folgt aus:

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' 29.12.2017
    3. ''' </summary>
    4. Private _shownAnswewsView As ICollectionView
    5. Public Property ShownAnswewsView() As ICollectionView
    6. Get
    7. Return _shownAnswewsView
    8. End Get
    9. Set(ByVal value As ICollectionView)
    10. _shownAnswewsView = value
    11. RaisePropertyChanged()
    12. End Set
    13. End Property
    14. Private _answersList As List(Of Answer)
    15. Public Property AnswersList() As List(Of Answer)
    16. Get
    17. Return _answersList
    18. End Get
    19. Set(ByVal value As List(Of Answer))
    20. _answersList = value
    21. RaisePropertyChanged()
    22. End Set
    23. End Property

    Könnte mir vorstellen dass im Konstruktor des VM so was in der Art rein müsste..

    VB.NET-Quellcode

    1. 'ShownAnswewsView = CollectionViewSource.GetDefaultView(AnswersList)
    2. 'AddHandler ShownAnswewsView.CollectionChanged, AddressOf AnswersListView_Changed

    Und dann die grosse Frage, wie füge ich dem context die neue Answer im AnswerListView_Changed bei?
    Vereinfacht die sache nicht, dass es um die Daten einer "child-Tabelle" geht, finde ich!
    Fragen über Fragen...und keine Antworten!

    Ist irgendwie noch zu weit weg.
    Kann mir bitte jemand weiterhelfe, so dass noch was aus diesem Samstag morgen werden kann?

    Danke,
    Jeiss

    Jeiss schrieb:

    Könnte mir vorstellen dass im Konstruktor des VM so was in der Art rein müsste..

    Warum im Konstruktor? Wenn ein Datensatz der Parent Tabelle selektiert wird, wird die ShownAnswers Liste (Observable) ja immer neu befüllt mit den Antworten der aktuellen selektion im Parent.
    Also solltest du genau dort wo dies passiert ansetzen!

    Anbei ein Beispiel welches ich dir auch ein wenig Kommentiert habe.

    Grüße
    Sascha
    Dateien
    • EF.zip

      (478,84 kB, 19 mal heruntergeladen, zuletzt: )
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    ach - jetzt findter wieder die mdf nicht.
    kann man das nicht so konfigurieren, dass derlei zips portabel sind?
    @Jeiss - bin ich in der Beziehung der einzige Noob, oder simmer da zwei?

    Und das eine Projekt könnte man doch auch mal rauswerfen.

    Ich hab da jetzt sowas gebastelt:

    VB.NET-Quellcode

    1. Public Sub New()
    2. If Not IsInDesignMode Then
    3. Dim pth = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
    4. AppDomain.CurrentDomain.SetData("DataDirectory", pth)
    Und inne App.Config gebe ich |DataDirectory| an:

    XML-Quellcode

    1. <connectionStrings>
    2. <add name="UrgentOrderContext" connectionString="metadata=res://*/UrgentOrdersModel.csdl|res://*/UrgentOrdersModel.ssdl|res://*/UrgentOrdersModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDB)\MSSQLLocalDB;attachdbfilename=|DataDirectory|UrgentOrdersModel.mdf;integrated security=True;connect timeout=30;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient"/>
    3. </connectionStrings>

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

    Hallo ErfinderDesRades,
    ​Ja klar kann das eine/alte Projekt in die Mülltonne!
    ​Dann würden wir den Verkehr im Internet weniger belasten, beim hin- und herschicken des Projektes.

    ​Also das mit der mdf, da kann ich dir auch nicht helfen.
    ​Das wird jetzt hier keiner glauben. Aber als dieser liebe EF-Model "Zauberer" mit dem SQL Skript die mdf erstellt hat, da hat der mich gar nicht mal gefragt wo die hin sollte.
    ​Der hat die einfach in "Meine Dokumente" gestellt. Hab mich auch gefragt wieso gerade dort und nicht "etwas näher ran" an den Projekt-Dateien....
    ​Aber in der app.config war der Pfad aber richtig.
    ​Und was ich mich auch frage. Wird heutzutage auch keine "Kopie" der mdf mehr in den Bin/Debug Ordner mehr kopiert?
    ​Ich kann mich immer nur wundern wie viele Fragen es gibt...... ?(

    ErfinderDesRades schrieb:

    ann man das nicht so konfigurieren, dass derlei zips portabel sind?

    Es ist schon schrecklich was ModelFirst hier macht. Unter CodeFirst ist ein ConnString nicht mal halb so lange weil man diese ganze MetaDaten-Grütze nicht angeben muss.
    Nicht umsonst gibt es ModelFirst unter EF Core nicht mehr, war immer ein murks und wird es immer sein.
    Vorallem, ich will ja später mal die DB laden können von wo ich will oder? Geht ja so gar nicht. Meines wissens nach kann bei EF 6 der ConnString nur aus der Config geladen werden ohne das ganze völlig zu verbiegen. Echt schade.
    Geht unter EF Core mühelos. Da gebe ich Ihn im Konstruktor mit.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    hier - ich hoffe, dassis als portable Basis brauchbar.
    bischen hab ich auch Solution+Projektnamen gekürzt
    Dateien

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

    Hi,
    ​ich hab glaube ich zumindest alle möglichen "locations" für die mdf probiert.
    Wo genau soll|DataDirectory|​ sein?
    ​Ich krieg auch einen Fehler gemeldet...beim starten.
    ​da fehlt auf einmal eine NuGet Referenz auf meinem Rechner?
    ​Hast du da auch was "gekürzt"?
    Das DataDirectory ist jetzt dein DokumentenOrdner - s.Post#55

    VB.NET-Quellcode

    1. Dim pth = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
    2. AppDomain.CurrentDomain.SetData("DataDirectory", pth)
    diese dolle Nuget-Auto-refresh hat bei mir nie funktioniert. Ich muss immer EF neu installieren - per Nuget.
    Kann am Framework liegen. Ich hab 4.5, aber vorgesetzt bekomme ich immer 4.5.2, und muss das auto-downgraden.