Laden...

Forenbeiträge von Palladin007 Ingesamt 2.079 Beiträge

02.12.2021 - 11:28 Uhr

Du könntest auch einen Wrapper entwickeln und als eigenen Prozess laufen lassen.
Wäre zwar eine ganze Ecke mehr Arbeit, weil Du ja auch mit dem Prozess kommunizieren musst, aber dann schmiert nur der zweite Prozess ab.
Den Prozess kannst Du dann überwachen und beim Absturz entsprechend reagieren.

Bei häufiger genutzten Bibliotheken halte ich aber die Gefahr für sehr groß, dass der Fehler im eigenen Code liegt.
Daher:

Schauen ob es ein Update der Bibliothek gibt

Versuchen den Fehler einzugrenzen

Schauen ob jemand anders den Fehler auch hat

Wären meine ersten Schritte

30.11.2021 - 22:10 Uhr

Die Datei wird erst dann entsperrt, wenn der Prozess beendet und damit auch die rooted reference wegfällt.

Das habe ich doch geschrieben?

Siehe:

Man verliert zwar die Kontrolle darüber, wann aufgeräumt wird und man riskiert Probleme im eigenen Programm, aber es wird spätestens nach dem Beenden des Programms alles aufgeräumt sein.

Was hier vielleicht noch fehlt:
Man riskiert natürlich auch Probleme in anderen Programmen, wenn die auf die gleiche Ressource zugreifen, solange der eigene Prozess noch läuft, aber die werden vermutlich (hoffentlich) damit umgehen können. Und diese Probleme sind - wie schon geschrieben - spätestens nach dem Beenden des eigenen Programms wieder beseitigt.

Ich beziehe mich auf den Blick von außen:
Gefährdung für die Hardware, dauerhaft gesperrte Datei-Leichen oder andere Probleme, nur weil man ein bisschen herum experimentiert und dabei nicht aufgepasst hat.

30.11.2021 - 19:06 Uhr

Ich glaube, ihr redet aneinander vorbei

Ja, ich glaube auch 😁

Für mich klang es zwischendurch so, als könne der Eindruck entstehen, es sei gefährlich, Dispose nicht aufzurufen. Diese Angst wollte ich nehmen.
Bei .NET sind alle Klassen so implementiert, dass - auch wenn man vergisst, Dispose aufzurufen - irgendwann automatisch alles Nötige aufgeräumt wird.
Man verliert zwar die Kontrolle darüber, wann aufgeräumt wird und man riskiert Probleme im eigenen Programm, aber es wird spätestens nach dem Beenden des Programms alles aufgeräumt sein.

Wenn man z.B. einen FileStream öffnet und den nicht richtig disposed, riskiert man zwar Fehler, aber die Datei bleibt nicht auf ewig im Windows gesperrt, nur weil man das Dispose (bei Streams geht auch Close) vergessen hat.
Für Code, der nicht von Microsoft stammt, kann man das natürlich nicht sagen, aber die meisten großen/bekannten Frameworks sind nicht weniger professionell entwickelt.

Man sollte natürlich trotzdem immer darauf achten (bis auf die sehr wenigen Ausnahmen), das erspart merkwürdige Fehler und bietet mehr Kontrolle.

30.11.2021 - 17:31 Uhr

Man muss also selbst alles korrekt implementieren, dass das funktioniert.

Wovon ich bei .NET-Klassen ausgehen würde - mir geht es nur um .NET-Klassen.
Bei allem, was man selber implementiert, muss man das natürlich auch selber sicherstellen.

30.11.2021 - 17:19 Uhr

Das implementiert dann aber kein IDisposable.

Mir ging es darum, dass alles was IDisposable implementiert, auch disposed wird - entweder mit Kontrolle im eigenen Code oder ohne Kontrolle im Destruktor.
Setzt natürlich voraus, dass alle Klassen, die unmanaged Ressourcen verwalten, im Destruktor auch aufräumen, mir ist aber keine bekannt, die das nicht tut.
Und für z.B. FileHandles gibt's ja die SaveFileHandle-Klasse (bzw. SaveHandle), die im Destruktor freigibt, was nötig ist und auch IDisposable implementiert.

Aber klar, wenn man sich "selber" unmanaged Ressourcen besorgt, muss man sie auch selber wieder freigeben.

30.11.2021 - 16:43 Uhr

.. was nur für .NET Runtime Objekte gilt; nicht für unmanaged / externe Windows Objekte.
Gerade im UI Bereich hat man aber oft Objekte, die man zwingend aufräumen muss.

Ich meine, dass die alle mit dem "vollständigen" Disposable-Pattern implementiert sind - sofern notwendig.
Also dass, wenn Dispose nicht aufgerufen wurde, es der GC am Ende tut, wie hier beschrieben.

Oder gibt's auch Klassen, die das nicht so machen?

30.11.2021 - 13:04 Uhr

Wo hab ich das Dispose her, naja es gibt auf YouTube unzählige "Lehr-Videos" wo es so gehandhabt oder vorgeschlagen wird!

Diese "Lehr-Videos" sind leider in den meisten Fällen wirklich nicht gut.

Und gegen Dispose spricht nichts, im Gegenteil, das Prinzip ist richtig und wichtig.
Aber man sollte verstanden haben, was es ist bzw. wofür es da ist und das Schließen von Fenstern gehört nicht dazu.
Dispose soll - verrät ja schon der Name - aufräumen, alles das, was nicht automatisch (z.B. durch den GC) aufgeräumt werden kann, also nicht verwaltete Ressourcen.

Beim WinForms-Fenster gehört unter Anderem dazu, über die WinAPI das Fenster zu entsorgen. Das kann der GC nicht alleine, da er keine Kontrolle über Windows hat.
Man könnte aber z.B. auch ein Gerät wieder in einen sicheren Zustand zurück versetzen.
Oder man ruft Dispose aller anderen Objekte auf - zumindest solange die Klasse auch die Kontrolle darüber hat.

Das heißt natürlich nicht, dass irgendetwas kaputt geht, wenn man kein Dispose aufruft, zumindest bei .NET kann man davon ausgehen, dass irgendwann trotzdem aufgeräumt wird.
Die Dispose-Methode gibt allerdings Kontrolle darüber, wann und unter welchen Bedingungen das gemacht wird, deshalb sollte man es (fast) immer auch aufrufen.

Mehr dazu:
Implement a Dispose method

27.11.2021 - 12:13 Uhr

Oder einfach den "sender"-Parameter casten, das sollte der Button sein.

25.11.2021 - 23:40 Uhr

Die Args müssen weiterhin Key-Value-Paare abbilden, einzelne Werte (z.B. nur ein Datei-Pfad) sind nicht möglich.
Den Key kannst Du dann benutzen, um den Wert zu bekommen, so wie man es mit IConfiguration so macht.
Man kann damit z.B. appsettings-Einträge durch die Kommandozeile überschreiben, muss dafür aber auch den passenden Wert verwenden.

Configuration in ASP.NET Core

22.11.2021 - 10:23 Uhr

Und Unterschiede gibt es kaum, das ist auch Absicht.
Der einzige mir bekannte Unterschied ist CodeLens, das ist in der Community etwas abgespeckt.

15.11.2021 - 09:43 Uhr

Auch die, die mit dem Verständnis nicht voran kommen, können ihr Problem schildern.

Z.B. könnte man beschreiben, wie man an einem konkreten Thema (nicht) verstanden hat. Das Thema aus eigener Sicht so gut wie möglich erklären, kann dabei auch helfen.
Und bei einer konkreten Aufgabe kann es auch helfen, zu beschreiben, was man schon alles versucht hat. Und die beliebte Aussage "Ich habe schon alles versucht" zählt nicht 😉

Jedenfalls bezweifle ich, dass Du hier einen Nachhilfe-Lehrer findest.
Ich habe keine Statistik, aber sehr wahrscheinlich sind die meisten hier berufstätig.

12.11.2021 - 09:59 Uhr

Der Fehler lag nicht an der PreRelease sondern generell an .NET 6 und wurde mit dem Release nicht gefixt.
Das Problem ist die "IncludePackageReferencesDuringMarkupCompilation"-Property, ihr Default-Wert wurde zwischen .NET 5 und 6 von false auf true geändert.
Man kann das Problem also "lösen", indem man in der Projekt-Datei folgendes in eine PropertyGroup schreibt:


<IncludePackageReferencesDuringMarkupCompilation>false</IncludePackageReferencesDuringMarkupCompilation>

11.11.2021 - 13:34 Uhr

Problem ist ich habe es mit einer parallel.for schleife getestet. Dort habe ich 100mal die Eigenschaft um eins erhöht und am Ende kam beim Ergebnis nicht 100 raus. Sondern unterschiedliche Werte wie 97,78,67... Deshalb frag ich mich wieso nicht 100 raus kommt. Ihr sagt ja mein lock ist richtig.

Du kannst die Property so threadsafe machen wie Du willst, das beeinflusst aber nicht die Reihenfolge, in der die Werte für die Property gesetzt werden.
Parallel.For nimmt die 100 und teilt sie auf deine Anzahl CPU-Kerne auf, sodass jeder Kern eine gleichmäßige Anzahl Aufgaben abzuarbeiten hat.
Das heißt aber auch, dass keine Reihenfolge sichergestellt ist und als letzter Wert alles bei raus kommen kann.

PS:

Ich bin von ungefähr diesem Code ausgegangen:


Parallel.For(0, 100, i => MyTestClass.MyProperty = i);

Aber Abts Annahme klingt realistischer, entsprechend passt auch seine Erklärung besser.

11.11.2021 - 11:54 Uhr

Vorweg: Statische Klassen mit einem statischen Zustand, der sich auch noch aus verschiedenen Threads heraus ändern kann - das ist garantiert eine ganz furchtbar schlechte Idee 😉

Und das Abrufen/Zuweisen einer Variable ist nicht das Problem, sondern was Du danach damit machst.
Beispiel:


if (_myIndex >= 0)
{
    var item = _myArray[_myIndex];
}

Hier kann sich zwischen dem if und der Verwendung im Array der Wert vom Index ändern.
Es kann also sein, dass der Array-Zugriff trotz der Prüfung zu einer IndexOutOfRangeException führt.

Das würde gehen:


var myIndex = _myIndex;

if (myIndex >= 0)
{
    var item = _myArray[myIndex];
}

Das Problem umgehst Du mit der Property aber sowieso, da sich der Wert, da Du beim Abrufen der Property ja das gleiche tust.
Bei komplexeren Abläufen (z.B. wenn mehrere Werte zusammen verarbeitet werden müssen) verwendet man dann lock, womit Du erzwingen kannst, dass nur ein Thread auf einmal ein Stück Code ausführt. Und dann gibt's noch diverse Kontroll-Strukturen (z.B. AutoResetEvent).

Aber das alles brauchst Du hier gar nicht, da deine Property nichts tut, was kaputt gehen könnte - sie ist bereits threadsafe.
Dafür müssen alle Klassen, die diese Property nutzen, sich um verschiedene Threads kümmern.

09.11.2021 - 10:41 Uhr

Aktuell müsste es die gleiche Version sein, behaupte ich.
Allerdings bekommst Du auch zukünftige Updates bevor sie offiziell released wurden.

08.11.2021 - 20:14 Uhr

VS2022 nutze ich schon eine ganze Weile als PreRelease.
Anfangs gab's hin und wieder Probleme, aber mittlerweile läuft es stabil und fühlt sich flüssiger an.

Was mir sehr schnell sehr ans Herz gewachsen ist, ist das Multi-Cursor-Feature.
Man kann mehrere Cursor setzen und damit arbeiten, das gab's vorher auch schon, die Cursor können jetzt aber unabhängig platziert werden und sowas wie STRG+Pfeil funktioniert auch.
Es gab Extensions, die das in der Form versucht haben, aber in VS2022 funktioniert's wirklich gut.

07.11.2021 - 21:34 Uhr

Verstehe ich das richtig, dass, wenn Du die "userList" bzw. "userListViewModel " anschaust, alle Einträge richtig sind, wenn Du "UCULVM" aber einzelne Einträge nicht mehr?

Deine Formulierung "sporadisch" klingt auch ein bisschen nach einem Problem im Zusammenhang mit Multithreading, ich vermute das Problem aber eher darin, dass Du mit jedem Mal Anzeigen der Liste im Debugger oder jedem Property-Aufruf eine neue Datenbank-Abfrage ausführst. Schau dir dazu die Funktionsweise von IEnumerable an, bei einer Liste oder ObservableCollection liegen die Items im RAM, wenn dahinter eine Datenbank-Abfrage steht (z.B. bei den ORMs) und Du sie nicht explizit ausführst und als Array oder Liste weiter verwendest, wird jedesmal, wenn Du damit etwas tust, die Abfrage erneut ausgeführt. Und die Datenbank garantiert ohne konkrete Sortierung keine Reihenfolge, die kann sich also allein durch das Anschauen im Debugger ändern.

Deine "userListViewModel "-Variable ist definitiv IEnumerable (weil LINQ), der Inhalt vom Select wird also definitiv jedes Mal auf's neue ausgeführt.
Bei der "userList"-Variable geht das aus dem Code nicht hervor.
Die ObservableCollection führt das IEnumerable auch einmal aus, um die eigene Collection aufzubauen, danach liegt alles im RAM.

In deinem Code gibt's aber noch einige andere Probleme:

Der Sinn der statischen Property erschließt sich mir nicht. Sieht nach einer Factory aus, nur als Property und nicht als Methode und ohne Vorteile.

Die Property gibt immer eine neue ObservableCollection zurück und ruft dafür auch immer wieder neu die Daten ab.
Zum Einen ist das unnötig und resultiert ggf. in einer anderen Reihenfolge und zum Anderen verliert damit die ObservableCollection ihren Sinn, da die EventHandler verloren gehen.

Eine Property sollte keine komplexe oder lang dauernde Arbeit verrichten und auf gar keinen Fall Datenbank-Abfragen ausführen.

Du arbeitest mit einem Repository aber ohne die Vorteile, die es bieten kann. Ohne globale Variablen kannst Du also keine DB-Verbindung offen halten und Du hast keine Möglichkeit, UnitTests zu schreiben, da dafür das Repository gemockt werden müsste.

Den Namen nach zu urteilen scheinst Du die Aufgaben/Schichten durcheinander zu werfen. Das ViewModel sollte nichts von der View wissen, warum heißt es dann "UserControl_"? Genauso das Repository, das sollte noch viel weniger davon wissen und trotzdem heißt es "UserControl_".

05.11.2021 - 22:24 Uhr

Die Frage, die ich mir stelle:

Brauchst Du Vererbung, oder willst Du dir nur Schreibarbeit ersparen?
Überleg dir gut, ob Du Vererbung nutzen willst, denn nachträglich wieder raus nehmen, kann sehr anstrengend werden.
Oder Du hast schnell einiges an zusätzlicher Komplexität, wenn die Daten größtenteils gleich sind, sich dann aber doch irgendein Detail unterscheidet.

Ersparen von Schreibarbeit ist mMn. nur dann ein Grund, wenn der gesamte Quellcode nicht mit der Basisklasse, sondern einem Interface arbeitet - also eine Art Default-Basis-Implementierung.
Bei den Records sieht die Vererbung eher danach aus, dass das Ziel "echte" Vererbung ist, also um auch die Konzepte zu nutzen und nicht nur um Schreibarbeit zu sparen.

Mir ist aber auch keine Möglichkeit bekannt, außer alles nochmal anzugeben.
Vermutlich geht das auch gewollt, denn bei manchen Funktionen ist ja auch die Reihenfolge der Werte wichtig.

Du könntest natürlich auch einfach normale Klassen nutzen - brauchst Du denn überhaupt das, was bei den Records generiert wird?
Was genau das ist, kannst Du dir mit einem Decompiler oder https://sharplab.io/ anschauen.

31.10.2021 - 14:27 Uhr

Gib doch in der Expression anstelle eines Func einen Delegate zurück - sollte denke ich funktionieren, ist aber ungetestet.

Ansonsten kannst Du mit einer generischen Klasse arbeiten, also folgende Syntax:


Controller<MyController>.Action((MyController x) => x.MyAction);

Die Action-Methode gibt's dann genauso oft, wie es Func-Delegaten gibt, also generisch mit einer beliebigen Anzahl generischer Parameter und am Ende einem Return.
Die Aufteilung in Klasse und Methoden ist notwendig, da Du, wenn Du einen generischen Typ angibst (den Controller) auch immer alle anderen Typen angeben musst.
Auf diese Weise gibst Du ihn an der Klasse an, bei der Methode kann der Compiler wieder Zucker drüber streuen.
Außerdem hätte das den nützlichen Neben-Effekt, dass Du die Parameter vom Compiler (zumindest die Typen) überprüfen lassen kannst.

Tatsächlich würde ich dein Vorhaben aber als Mikro-Management bezeichnen und es auch so machen:


RedirectToAction<ProductsController>(nameof(ProductsController.Details), new { id = 1234 });

Zumindest bei produktiven Projekten - privat ist so eine Klasse sicher ein nettes kleines Projekt und spart danach auch etwas Zeit ein. Produktiv dürfte die Ersparnis aber vom Aufwand der Entwicklung dieser Klasse sowie späterer Wartung aufgefressen werden.
Außerdem kann Performance ein Problem werden - Expressions sind langsam und groß (viel zu tun für den GC), aber dazu können Abt oder gfoidl sicher noch mehr sagen.

PS @Abt:
Ich glaube, hier geht es wirklich nur um die kleine Code-Optimierung, dass man Controller und Action immer, wie im ersten Snippet gezeigt, angeben muss.
Oder es geht darum, dass der Controller-Name immer Klassen-Name ohne "Controller" am Ende ist, man kann also kein nameof benutzen.
Also eine kleine Schreibarbeit-Ersparnis für etwas, das es so mehr oder weniger schon gibt.
Zumindest habe ich es so verstanden.

27.10.2021 - 10:39 Uhr

Du erstellst ein zweidimensionales Array, füllst es aber nicht mit Daten und ignorierst beim Schreiben des Arrays in die Konsole, dass es zweidimensional ist.

Schau dir an, was ein zweidimensionales Array ist und wie man es benutzt, dann wird es sicher auch etwas klarer.

27.10.2021 - 08:53 Uhr

Ein Array ist nur eine Datenstruktur und kennt keine Formatierungen. Die Aufteilung im Code ist nur im Code, der Compiler liest das als eine Zeile.
Du schreibst in deiner for-Schleife jedes Item nacheinander, da ist nirgendwo ein Zeilenumbruch, also wird auch kein Zeilenumbruch angezeigt.

Entweder Du verwendest ein zweidimensionales Array
Oder Du fügst immer dann eine neue Zeile ein, wenn Du eine neue Zeile haben willst.

25.10.2021 - 14:31 Uhr

Dann knallt es -> fail fast.

Bei meinem Test lief es.
Vielleicht liegt das aber auch einfach daran, dass der Unterschied ziemlich klein ist.
Wenn z.B. nur .NET 6 installiert ist, dann darf es ruhig knallen 😁

25.10.2021 - 13:53 Uhr

Habe ich mir auch schon überlegt.
Aber was für Auswirkungen hat es, wenn die konkrete Version nicht installiert ist?

Und ich hab aktuell bei mir 5.0.401 und 5.0.402 installiert, keine 5.0.400.
Bei meinem kleinen Text hat's funktioniert, aber einen Beigeschmack hat's trotzdem irgendwie.
Schöner wäre natürlich, wenn es Wildcards unterstützen würde 😠

25.10.2021 - 10:53 Uhr

Ok, ich hab eine Lösung.

Eine global.json mit folgendem Inhalt neben die sln-Datei:


{
  "sdk": {
    "allowPrerelease": false
  }
}

Im Projekt ist .NET 5 eingestellt, aber den Compiler nimmt er scheinbar immer von der neusten Version und das ist bei mir .NET 6 RC2.

If you are in Visual Studio, it uses the prerelease status requested. That is, if you're using a Preview version of Visual Studio or you set the Use previews of the .NET Core SDK option (under Tools > Options > Environment > Preview Features), the default value is true; otherwise, false.

Zitat von hier: global.json overview - .NET CLI

Also bin ich wohl selber schuld 😠

22.10.2021 - 17:09 Uhr

Hi,

ich arbeite mit WPF, .NET 5 und VS2022 Preview.
Außerdem habe ich eine Directory.Build.props, in der ich Firmen- und Projekt-Name vor Namespace und Assembly hänge.

Die Directory.Build.props enthält also sowas:


<PropertyGroup Condition="!$(MSBuildProjectName.StartsWith('$(ApplicationName).'))">
	<RootNamespace>$(ApplicationName).$(MSBuildProjectName)</RootNamespace>
	<AssemblyName>$(ApplicationName).$(MSBuildProjectName)</AssemblyName>
</PropertyGroup>

$(ApplicationName) ist dann z.B. "Firma.Produkt".

Im Startprojekt habe ich ein CustomControl vom Template hinzugefügt.
Es wurde also ein CustomControl.cs und eine Generic.xaml erstellt, in der dann der Style für das Control steht.

Die XMLNS-Definition:


xmlns:local="clr-namespace:Firma.Produkt.MyApp"

Das Problem ist:
Mit der AssemblyName-Zeile in der Directory.Build.props funktioniert es nicht.
Nehme ich die AssemblyName-Zeile aus der Directory.Build.props raus, funktioniert es.

Folgender Fehler:

Fehlermeldung:
The name "CustomControl1" does not exist in the namespace "clr-namespace:Firma.Produkt.MyApp".
The name "CustomControl1" does not exist in the namespace "clr-namespace:Firma.Produkt.MyApp".
Cannot find the type 'local:CustomControl1'. Note that type names are case sensitive.

Die Namespaces habe ich gefühlt 100 Mal kontrolliert, die stimmen also.
Namespace und AssemblyName sind - wie man oben sieht - auch identisch.
Der XAML-Editor erkennt mein Control auch, zumindest bietet er es mir in der Intellisense an.

Ist das ein Bug?
Habe ich was übersehen?

Im Anhang ist ein minimalistisches Beispiel-Projekt, einfach die AssemblyName-Zeile in der csproj ein- bzw. auskommentieren.

07.10.2021 - 19:51 Uhr

Sorry, mein Edit und Dein Post haben sich überschnitten.

Wenn man MemoryExceptions nicht abfangen kann, gibt es dann wenigstens eine Möglichkeit zu überprüfen, ob auf jene Stelle im Memory gerade zugegriffen werden kann?

Die konkrete Stelle hilft dir nicht weiter, die .NET Runtime schaufelt doch immer hin und her - solltest Du das verhindern/umgehen, dann hast Du schon deinen Fehler 😉
Und ich denke, Abt meint die OutOfMemoryException. Wann die geworfen wird, steht in der Doku und dann hat man nicht nur irgendeine Stelle im RAM.

30.09.2021 - 17:26 Uhr

Was Du vor hast, wird so funktionieren, langfristig aber zu Problemen führen 😉
Du machst damit die Klassen von den in einer Methode fix definierten Parameter abhängig und musst bei jeder Änderung daran denken, dass Klasse und Reflection-Code noch zueinander passen müssen.
Zum Spielen und Reflection kennen lernen, ok, aber sobald daraus ein tatsächliches Projekt wird, solltest Du lieber andere Wege suchen.

Für Datenbanken wären das z.B. EFCore, das hat das gleiche Problem, hat aber auch viel Logik nur dafür, dass diese komplexen Reflection-Zusammenhänge genau so funktionieren, wie man es erwarten würde.
Für alles Weitere könnte man auf Konzepte wie das Factory-Pattern zurückgreifen oder sein Vorhaben überdenken, dass man gar keine dynamisch erzeugten Instanzen braucht.
Selbst implementierte Reflection würde ich immer möglichst vermeiden oder wenigstens klein halten.

28.09.2021 - 11:09 Uhr

Das geht nur mit Reflection.
Du suchst dann per Reflection die Properties oder den Konstruktor, den Du brauchst und arbeitest damit.

Oder Du erfindest ein Interface, dem Du eine Methode gibst, das Name und Wert bekommt.
Die Implementierung muss dann je nach Entity separat schauen, was das ist und wie man es setzt.

Aber was Du versuchst, wurde schon zig Mal entwickelt, nennt sich ORM.
Z.B. EFCore, nHibernate oder Dapper.
EFCore ist vermutlich der modernste ORM, wo nHibernate heute steht, weiß ich nicht.
Dapper ist sehr einfach gestrickt und beschränkt sich auf das Mapping (das, was Du versuchst), während EFCore und nHibernate die komplette Datenbank-Schicht abbilden können, sodass am Ende gar kein (oder kaum) SQL mehr notwendig ist.

Wenn es dir nur um den Spaß an der Freude oder Übung geht, dann liegt es bei dir, was Du versuchst.
Produktiv würde ich aber immer auf einen der ORM setzen, entweder EFCore oder Dapper, je nach Anforderungen.
Eine eigene Reflection-Lösung würde ich nicht mehr entwickeln, sowas ufert schnell aus und in Dapper gibt's das ja schon.
Und die Interface-Lösung ist sehr einfach, aber auch unflexibel und langfristig aufwändiger.

20.09.2021 - 00:11 Uhr

Dem, was FZelle sagt, kann ich nur zustimmen.

Es gibt bei Windows aber ein Tool, das zuverlässig und sicher aufräumen kann und das ist Windows selber.
Schau dir die Datenträgerbereinigung an, die räumt auf, was sicher aufgeräumt werden kann.

Den Rest musst/solltest Du selber aufräumen.

Oder Du installierst regelmäßig Windows neu, sollte man sowieso immer mal wieder machen.
Das ist mehr Aufwand, aber die mit Abstand effektivste Methode, den ganzen selbst verschuldeten Müll weg zu bekommen.
Außerdem hilft das bei der Organisation der eigenen Daten.

09.09.2021 - 15:32 Uhr

Verschlüsseln geht nicht, wie soll der PC es sonst ausführen?
Und wenn das Programm sich selbst entschlüsselt, muss der Key irgendwo stehen und den kann man dann wieder auslesen und den Code selber entschlüsseln.
Und Reflection kannst Du auch nicht verhindern, das liest nur die Metadaten jeder .NET-Assembly und ohne diese Metadaten funktioniert .NET nicht mehr.

Reflection dürfte auch weniger das Problem sein, sondern dass jemand deine Assembly dekompilieren möchte, richtig?
Auch das kannst Du nicht verhindern, aber Du kannst es erschweren, den Code zu verstehen. Dafür gibt's Obfuscation, bzw. Tools, die das anbieten.
Empfehlen kann ich da aber nichts, ich habe damit noch keine wirklichen Erfahrungen, aber wenn Du nach "Obfuscation" suchst, findest Du garantiert einige Artikel im Internet.

01.09.2021 - 10:46 Uhr

Lies dich mal in die TemplateParts, damit kannst Du aus dem Code heraus einen Teil des Templates erreichen.
Ob das die bessere Option ist, sei mal dahin gestellt, aber es ist eine Option.
Im Zweifel würde ich mich aber auch für deine Lösung entscheiden, die ist offensichtlicher 🙂

25.08.2021 - 00:54 Uhr

Achso, die Kritik, dass Du keine Antwort bekommen hast, bezog sich gar nicht auf dieses Forum? Den Teil hab ich im ersten Beitrag wohl überlesen ^^
Aber wenn's eine andere Sprache ist, weiß ich nicht, ob Du hier so viel Erfolg haben willst, der Großteil ist hier immerhin im .NET-Bereich aktiv.

Stell einfach deine Frage und schreib einen Link zum alten Thema und den Grund für den CrossPost.
Das versteht denke ich jeder, kann ja immer mal vorkommen und verscheuchen will dich auch niemand.
Es geht denke ich hauptsächlich darum, dass die Antworten auch gewertschätzt werden und dass über Foren-Grenzen hinweg keine Diskussion entstehen kann.

24.08.2021 - 23:14 Uhr

Verbietet dir niemand, also frag halt.
Aber warum fragst Du nicht hier nochmal im selben Thema, wenn Du keine hilfreiche Antwort bekommen hast?
Oder hat dir die Antwort nicht gefallen? In diesem Fall ist die Chance groß, dass es in einem anderen Forum ähnlich laufen wird.

21.08.2021 - 22:46 Uhr

..., dass die Solution Organisation nicht so ist, wie sie sein sollte (bitte keine Diskussion nun)

Du möchtest keine Diskussion dazu, aber hast Du Quellen dazu? Ich will nicht diskutieren, sondern mich nur belesen ^^
Ich kenne nur deinen eher auf Übersicht ausgelegten Artikel zur Ordner-Struktur: [FAQ] Ordnerstruktur für .NET Projekte
Ob und wie ich VisualStudio durch die Solution-Organisation optimieren kann, würde mich aber sehr interessieren.

15.08.2021 - 15:07 Uhr

Was Du schreibst, klingt ein bisschen so, als wär euer Logging selbst geschrieben?
Wenn das so ist: Lasst es bleiben. Ich habe schon ein paar solcher Lösungen gesehen und die hatten bisher alle mehr oder weniger große Probleme, die sich teilweise nicht mal richtig beseitigen ließen und meist erst aufgefallen sind, wenn es am wenigsten passt.
Nutzt ein vorhandenes Logging-Framework, die kümmern sich auch um Performance. Serilog ist z.B. sehr beliebt, oder Microsoft.Extensions.Logging (quasi alle Logging-Frameworks unterstützen das), was in ASP.NET Core mit dabei ist. Oder log4net, ich mag's aber nicht.
Und ich würde nicht auf eine Queue verzichten. Exceptions kannst Du global abfangen und in diesem Ausnahmefall die Queue abarbeiten lassen. Die paar Fälle, wo das nicht geht, sind selten und bei z.B. einer StackOverflowException ist auch egal, dass nicht alles im Log steht, Du hast das sowieso zigfach wiederholt drin stehen.

Für z.B. Serilog und Microsofts Logging gibt's garantiert auch Erweiterungen, die an einen Logging-Server senden, entsprechende Server-Software vorausgesetzt, damit habe ich aber keine Erfahrung.
Ansonsten tut's auch eine simple ASP.NET Core API, die das entgegen nimmt und weg schreibt.

Ich persönlich würde schauen, was es bereits für Lösungen für Serilog gibt und dann ggf. die verwenden.
Alternativ setze ich die kleine ASP.NET Core API hin, den Sink für Serilog zu schreiben ist danach kaum Arbeit.

11.08.2021 - 09:39 Uhr

Such doch einfach bei NuGet nach odbc
Erstes Ergebnis.

Abgesehen davon ist Access keine Datenbank und solange Du nicht aus irgendwelchen Gründen gezwungen bist, solltest Du eine richtige Datenbank verwenden.

10.08.2021 - 10:24 Uhr

@Abt:
Kennst Du eine gute Übersicht von Microsoft zu diesen Zusammenhängen?
Gerade für Einsteiger kann das ja ziemlich verwirrend sein, da würde eine Übersicht helfen.

10.08.2021 - 01:31 Uhr

Das geht nicht, steht doch in der Meldung: "ist nicht möglich"

Entweder Du gehst mit der Version runter (was bescheuert wäre) oder Du ziehst die Version hoch. Für Letzteres gibt's Doku zum migrieren.

Oder Du verwendest .NET Standard 2.0 anstelle von .NET 4.7.1, das kannst Du dann sowohl in .NET 4.7.1 als auch .NET Core 3.1 einbinden. Wie gut das mit WinForms funktioniert, weiß ich aber nicht.
Und bedenke, dass .NET Standard nicht mehr weiterentwickelt wird, das sollte man nur noch nutzen, wenn man die Kompatibilität für alte Frameworks braucht.

Besser wäre, Du nutzt überall .NET Core oder Neuer - sofern möglich.

06.08.2021 - 08:54 Uhr

... generell das ganze Buch.

Wer Bereit ist, die 50€ auszugeben, kann auch direkt zum Nachfolger (Visual C# 2019) greifen.

06.08.2021 - 02:51 Uhr

Eine Initialisierung ist sowas:

Deine Beispiele sind Deklaration und Initialisierung in einem.
Richtig wäre:


string email; // Deklaration
email = "abc@def.ghi"; //Initialisierung

Eine Definition ist sowas wie eine Funktion, also beispielsweise das hier

"Definition" ist meines Wissens nach gar nicht genauer belegt, ich würde darunter aber alles verstehen, wo irgendetwas eindeutig "beschrieben" wird, also auch Methoden, Klassen, Variablen, völlig egal was.
"Funktionen" sind in C# aber etwas anderes, was Du gezeigt hast, ist die Definition einer Methode.

Wann in der Praxis verwendet man public und wann kommt private zum Einsatz und

Man überlegt sich, wann man etwas public braucht, alles andere bleibt private.
Das Thema heißt Kapselung - solltest Du dir anschauen, ist ein wichtiger Bestandteil von OOP.

warum macht man nicht alles public?

Zur Sicherheit - Du lässt ja auch nicht jeden dein Geld überweisen, das willst Du schön selbst machen und dabei kontrollieren.

Dann gibt es noch protected, aber das scheint eine Sonderform zu sein

Keine Sonderform, aber nur bei Vererbung relevant.
Sonderformen wären "internal", "private protected" und "protected internal".

Bei Funktionen wird wohl immer public genommen

Natürlich nicht, aber es gibt leider viele, die das machen.
Man sollte sich immer überlegen, was von außen erreichbar sein soll und was nicht.

Ich persönlich versuche immer so wenig wie möglich public zu machen, eben nur das, was ich auch brauche. Dadurch muss ich in den Methoden nicht sicherstellen, dass sie auch gefahrlos von außen benutzt werden können und ich brauche keine Probleme mit anderen Code befürchten, wenn ich sie ändere.

Bei Funktionen kenne ich nur den Zusatz "void"

Völlig anderes Thema.
"void" meint, dass die Methode keinen Rückgabewert hat.

04.08.2021 - 19:20 Uhr

Ja - hab's gerade nochmal getestet.
Keine Cookies = bei jedem Login eine Email

Ergibt aber auch Sinn, wie soll der Server den Browser sonst identifizieren können?
Vielleicht kann man sich aus den UserAgent-Daten eine Art ID zusammen basteln, wirklich eindeutig ist das aber nicht und damit auch nicht sicher.

04.08.2021 - 16:48 Uhr

Die Mail sollte doch nicht so oft verschickt werden?
Soweit ich das mitbekommen habe bekommst Du die nur, wenn Du einen anderen PC oder Browser verwendest, den Du vorher noch nicht verwendet hast.
Solange das so bleibt, halte ich das auch für sehr wichtig.

Vielleicht hängt das mit (nicht gespeicherten) Cookies zusammen?

03.08.2021 - 12:38 Uhr

Der blaue Kreis von Windows, wenn ein Programm nicht antwortet?
Dann tust Du zu viel im UI-Thread - sollte man nicht tun.
Oder Du hast einen Deadlock, der den UI-Thread dauerhaft blockiert.

Das hat aber nicht pauschal etwas mit Debug vs. Release zu tun, zumindest nicht bei .NET.
Du hast wahrscheinlich irgendetwas, was sich im Release anders verhält und zu dem Problem führt.

Wie Du das findest, kann dir hier niemand sagen, da gibt's massig Wege.
Wenn Du es im Code oder beim Debuggen nicht identifizieren kannst, kannst Du alternativ so lange kleine Teile des Start-Prozesses raus werfen, bis es nicht mehr blockiert - was Du zuletzt raus geworfen hast, ist dann die Ursache.

29.07.2021 - 12:45 Uhr

Man kann die WinAPI (und andere) Funktionen mit C# aufrufen.
Die Technologie dafür heißt "p/invoke"
Hilfreich ist da die Website pinvoke.net.

29.07.2021 - 10:05 Uhr

Was Du mit den Predicates machen willst, geht langfristig in die Hose.
Es gibt/gab zwar ein Framework, das eine LambdaExpression als String de/serialisiert, das könntest Du dann speichern, aber wie gesagt: Das geht in die Hose ^^

Besser wäre aber, Du denkst um und beschränkst dich auf das, was mit der Datenbank geht.
Z.B. eine Art Mapping, welcher Config-Eintrag mit welchem Key/Value geprüft werden soll oder ob der Wert ein Regex-Pattern ist und so weiter.

Prinzipiell schon, verwendet zB EF unter der Haube.

Hast Du einen Namen oder Link oder eine Quelle?
Hier steht kein Provider dafür.
Oder gibt's das nicht als eigenes Packages, sondern nur intern in EFCore?
So ein DB-Provider ist eigentlich das Einzige, was ich da noch vermissen würde.