Hallo Abt
Danke! Ja das ist allerdings eine ältere Anwendung die ich übernommen habe und ich darf sie nicht komplett umbauen.
Hier geht es aber nicht um die Datenspeicherung, sondern nur um die Darstellung beim Öffnen des Fensters. So etwas sollte eigentlich nicht passieren.
Vielleicht hat noch jemand eine Idee?
Hallo Jamikus!
Danke für die wirklich clevere Idee! - Ja ich habe die Position gefunden.
Im Loaded wird bLF immer mit false angezeigt, aber im Loaded werden auch einige Radiobox_Checked() aufgerufen und sobald der Debugger da im Einzelschritt hineinspringt, wird darin teilweise bLF=true angezeigt! Nach dem Herausspringen aus der Radiobox_Checked() ist aber bLF im Loaded wieder korrekterweise false!
Im Loaded ändert es sich also nicht, aber in den Untermethoden ist der Wert bLF teilweise(!) falsch.
(Nein ich habe keine lokale Variable in den Untermethoden, die auch bLF heißt. Wenn ich in der Untermethode in der Abfrage if (bLF==true) den Cursor auf bLF platziere und dann F12 drücke, komme ich genau zu meiner definierten bLF - Variable aus dem Window.
Ich bin total ratlos.
Hallo!
In einem C# WPF-Projekt wird in "Window1 (Hauptfenster)" das "Window2" geöffnet und darin "Window3". (Jeweils mit einer lokalen Var und .Show())
public partial class Window3 : Window
{
private bool bLF = false;
...
}
Im Window3 wird am Ende von Loaded() bLF auf true gesetzt.
Später wird Window3 geschlossen und danach von außerhalb(!) dieser Fenster Window3=null gesetzt und danach Window2 ebenfalls geschlossen und Window2=null gesetzt und danach jeweils GC.Collect() sowie GC.WaitForPendingFinalizers() ausgeführt. (Ja ich habe hier oft gelesen, GC ist nicht notwendig).
Öffnet man nun wieder Window2 und dann Window3 jeweils normal mit .Show(), ist in Window3 bLF immer noch auf true gesetzt, obwohl das Fenster Window3=null gesetzt war!
So etwas habe ich bislang noch nie gesehen. Scheint eine hängende Referenz zu sein?
Ich habe nun versucht zu sehen, wo genau bLF auf true umgestellt wird:
internal Window3()
{
MessageBox.Show("Zeile1 bLF=" + (bLF == true ? "true" : "false"));
InitializeComponent();
MessageBox.Show("Zeile 2 bLF=" + (bLF == true ? "true" : "false"));
bLoadedFinished = false;
MessageBox.Show("Zeile 3 bLF=" + (bLF== true ? "true" : "false"));
}
Beim erneuten Öffnen ist bLF in Zeile 1 false (so wie es sein soll) und dann aber nach InitializeComponent() seltsamerweise auf true, obwohl es erst am Ende von Loaded auf true gesetzt wird! bLF wird sonst wirklich nirgendwo auf true gesetzt.
Wenn man zum Test bLF vor dem Schließen des Window3 auf false setzt, ist es dann nach dem Erneuten Öffnen von Window3 korrekt auf false! Es behält also seinen alten Wert, obwohl das Fenster mit .Close() und window3=null geschlossen wurde und der GarbageCollection bereinigt wurde. Das erneute Öffnen erfolgt ca. 1 Min. danach, wodurch eigentlich die GC genügend Zeit hätte den Speicher zu bereinigen.
Im Windows-Task-Manager geht die Speicherauslastung beim Schließen des Window3 schon etwas herunter, aber nie auf die Werte vor dem Öffnen des Fensters Window3. Ja, ihr schreibt, der Taskmanager ist ungenau.
Die einzige Referenz die auf Window3 besteht ist eine ObservableCollection außerhalb der Fenster mit einer Klasse die ein Feld "public Window Window { get; set; }" besitzt und der das Fenster zugewiesen wird, wenn es geöffnet ist. Allerdings wird dieses Feld dann beim Schließen auch auf null gesetzt und danach das komplette Item mit .Remove(item) entfernt.
Was läuft da falsch?
Vielen Dank!
Hallo Abt und MrSparkle!
Ich bin jetzt aus dem Urlaub zurück; Gesund.
Danke für die Antworten und den Link. Ich werde es beherzigen und mir nun Planungszeit für die Umsetzung in den Kalender eintragen.
Ich wünsche eine vielversprechende Woche!
Hallo Abt!
Es ist schwierig, wenn man immer angetrieben wird, sofort neue Ergebnisse zu liefern und keine Zeit für diese Dinge einplanen kann.
Ich denke in größeren Firmen ist das besser gelöst.
Kennst Du auch keine gute Seite zur Umstellung von EF 6 auf EF Core in englisch? Vielleicht hat noch jemand einen Tipp.
Nochmals vielen Dank!
Hallo Witte!
Danke, aber damit wäre nur ein Select möglich, kein zurückschreiben in die Tabelle "Einladungen".
Hallo Abt!
Danke auch Dir nochmals! Zeitlich ist es für mich sehr schwer mich neben meiner Arbeit auch mit den Änderungen etc. zu befassen. Ich hatte das schon im Hinterkopf auf dem Radar, aber mich noch niemals damit befasst. Erschwerend kommt hinzu, dass ich beim EF den Designer nutze und den "Database First"-Ansatz.
Ich weiß, es gibt einige Infos zur Umstellung auf EF Core. Aber kennst Du hierzu zufällig eine gut gemachte und verständliche Seite auf Deutsch?
Vielen Dank!
Hallo Abt!
Danke für die ausführliche Antwort! Das hilft wirklich sehr!
Ja, ich nutze noch nicht den EF Core - Sollte ich irgendwann umstellen, weil der normale EF irgendwann nicht mehr unterstützt wird? Wann wird das vermutlich sein? - Microsoft behält sich da sehr bedeckt.
https://docs.microsoft.com/de-de/ef/efcore-and-ef6/porting/
Hier schreibt Microsoft:
"...Aufgrund der wesentlichen Änderungen in EF Core wird nicht empfohlen, eine EF 6-Anwendung auf EF Core umzustellen – es sei denn, es gibt einen zwingenden Grund für eine solche Änderung. Sie sollten den Wechsel von EF 6 nach EF Core weniger als Upgrade, sondern als eine Portierung betrachten..."
Könnte es sein, dass das normale EF ab einem bestimmten VS nicht mehr genutzt werden kann? (z. B. VS 2021, 2023, 2025, 2027 etc.?)
Nun nochmals zum Problem:
Kunden.Name soll nur beim Lesen gleichzeitig aus der Tabelle Kunde ausgelesen werden (damit der Benutzer den Kundennamen im Klartext sieht, aber beim folgenden Speichern natürlich nicht zurückgeschrieben werden.
Ich dachte, vielleicht kann man im Linq mit "select new {…." alle Felder angeben und dann das Ergebnis in eine Entität vom Typ "Einladung" vornehmen. - Und in der partial class Einladung ist ja dieses (public string Name { get; set; } definiert, in das der Kundenname beim Linq-Befehl übernommen werden kann.
Wenn es so nicht geht, habe ich vermutlich den Post in Stack Overflow falsch verstanden? (letzter Eintrag von Sean, ganz unten)
Ein Locking ist in diesem Programmteil nicht notwendig.
Wenn ich nach dem Linq auf die Tabelle "Einladung" das Feld "Name" manuell beschreibe, klappt ja ein anschließender SaveChanges() auch korrekt und der Befehl ignoriert einfach dieses "lokale" Feld "Name".
Einen zweiten Select und eine foreach-Ersetzung würde ich gerne vermeiden.
Du bist sehr weit und hast eine enorm große Kenntnis und würdest vieles auch ganz anders realisieren. Evtl. kann man diesen Select aber dennoch in einer möglichen Form realisieren.
Danke und schöne Grüße!
Hallo!
Ich nutze VS 2017, C# und den SQL-Server.
Hier ein vereinfachtes Beispiel (was natürlich nicht sehr sinnvoll ist):
Eine SQL-Server Tabelle "Einladung" enthält folgende Spalten:
EinladungID
KundeID
Hinweis
Eine zweite Tabelle "Kunden" enthält folgende Spalten:
KundeID
Name
1.) Select: Alle Kunden zur Einladung Nr. 100 heraussuchen:
var i = (from e in dataEntities.Einladung
where e.EinladungID==100
select o).ToObservableCollection<Einladung>(...
-> Das klappt. Man erhält eine ObservableCollection mit den Spalten EinladungID, KundeID und Hinweis und ich kann auch Änderungen mit SaveChanges() speichern.
2.) Nun erweitere ich im C#-Code die partielle Klasse "Einladung"
(public partial class Einladung)
um ein Feld "Name" (public string Name { get; set; }), welches nicht in der SQL-Tabelle "Einladung" existiert, aber den Benutzer in der Observable Collection angezeigt werden soll. Damit würde er auch immer den aktuellen Namen aus der Tabelle "Kunden" sehen, auch wenn der sich einmal ändert.
Ohne Probleme habe ich durch diese Erweiterung ein zusätzliches Feld "Name", das ich auch beliebig beschreiben und ändern kann und welches gewünschterweise bei SaveChanges() natürlich nicht in die Tabelle "Einladung" zurückgeschrieben wird. Alle anderen Änderungen an der Tabelle "Einladung" werden aber mit SaveChanges() korrekt in den SQL-Server zurückgeschrieben.
--> Frage. Wie kann ich aber per Linq-Join dieses Feld "Name" zusätzlich auslesen, so dass es bei SaveChanges() ignoriert wird. Das hier klappt leider nicht:
var i = (from e in dataEntities.Einladung
where e.EinladungID==100
join a in dataEntities.Kunden on e.KundeID equals a.KundeID
select e, a.Name).ToObservableCollection<Einladung>(...
Es sollte so ausgelesen werden, dass alle Änerungen per SaveChanges() in die Tabelle "Einladung" gespeichert werden können, ohne das das Feld "Name" berücksichtigt wird.
Ich möchte ungern einen zweiten Select auf die Kundentabelle ausführen und dann per foreach alle Datensätze in der Observable Collection einzeln durchgehen müssen.
Ein T-SQL-Befehl würde diesen Join zwar machen, jedoch kann ich dann nicht mehr mit SaveChanges() Änderungen zurückspeichern.
Folgenden Lösungsvorschlag habe ich entdeckt:
https://stackoverflow.com/questions/23848259/linq-updating-different-table-after-join-process
Umformuliert wäre das so, das klappt leider nicht:
var i = (from e in dataEntities.Einladung
where e.EinladungID==100
join a in dataEntities.Kunden on e.KundeID equals a.KundeID
select new { e, a }).Select(result => { result.e.EinladungID = Einladung.EinladungID; result.e.KundeID = Einladung.KundeID; result.e.Hinweis = Einladung.Hinweis; result.a.Name = Name; return result}).ToObservableCollection<Einladung>(…
Wie bekommt man so etwas hin?
Danke sehr!
Hallo Abt
In Ordnung. Verstanden. Vielen Dank für die Infos. Ihr tut hier wirklich einen sehr guten Job, auf diese Fragen einzugehen! 👍
Mit freundlichem Gruß
Hallo Abt
In Ordnung. Ich dachte im Forum gibt es dazu Erfahrungswerte und man kann sich dazu einfach austauschen und nicht, dass jeder selbst immer von vorne anfängt. 🙁
Ich werde dann viele Daten erzeugen und dann Tests fahren.
Danke trotzdem für die Antworten.
Mit freundlichem Gruß