Vorschoben aus Windows Forms, da offensichtlich eine Webanwendung dahinter steckt.
Hallo,
ich habe eine XML-Datei die in Ausnahme fällen schon mal von zwei Usern gleichzeitig geändert werden kann. Seltend, aber kann passieren. Nun möchte ich den Schreibvorgang einmantel wie folgt:
File.SetAttributes(MapPath("test.xml"), FileAttributes.ReadOnly);
bearbeiten der XML
speichern der XML
File.SetAttributes(MapPath("test.xml"), FileAttributes.Normal);
funktioniert das? Kann ich so einen doppelten zugriff verhindern? Arbeitet das alles schnell genug?
Lass den FileStream nach dem laden doch offen. Dann ist sie gesperrt
Ich nutze den filestream nicht.
ich nutze Xdocument.load und save
wie holt man sich den ne xml mit dem filestream?
Steht doch alles in der MSDN....
Hm ich verstehe das im Moment noch nicht alles.
XDocument Depot = XDocument.Load(MapPath("test.xml"));
Depot.Add(new XElement("neues"));
Depot.Save(MapPath("test.xml"));
Wenn ich es so schreibe kann es passieren, dass wenn zwei dies gleichzeitig versuchen eine Variante gewinnt und die andere ist weg.
Wie kann ich nun Xdocument.Load offen lassen?
Wenn ich es so schreibe kann es passieren, dass wenn zwei dies gleichzeitig versuchen eine Variante gewinnt und die andere ist weg
Zwei was? User? Programminstanzen? Prozesse? Threads? Programmierer?
Und was genau meinst du mit "gewinnen" und "weg" sein?
Wie ich schon im Startbeitrag geschrieben meine ich zwei User die gleichzeitig die xml ändern wollen. Dies muß ich verhindern. Das wollte ich erreichen in dem ich die Datei in den Readonly-Modus setze.
Wenn ich Dein MapPath richtig deute, nutzt Du eine Webapplikation.
Dann wäre aber Windows Forms der falsche Forenbereich.
Du hast also das Problem, dass Du aufgrund der verschiedenen Threads (2 Request - 2 Threads) nicht zeitgleich auf die Datei zugreifen kannst.
Dein Vorhaben ist aber in Deiner Beschreibung widersprüchlich:
Du willst, dass nur einer Schreiben kann (aufgrund des Lockings) aber Du willst auch nicht, dass die Daten aus dem zweiten Request verloren gehen, wenn der erste Request noch aktiv ist.
Dies ist eine Patt-Situation, da Du einen Request nicht warten lassen solltest, was Du aber bei einem gelockten File tun musst, wenn Du die Daten nicht verlieren willst.
Lösung des ganzen ist, außerhalb der beiden Request den Vorgang synchron zu halten.
Sprich Du hast eine Queue, in der die Änderungen reinkommen. Hierbei können aus allen möglichen Threads(analog Requests) die Queue gefüllt werden.
Du hast aber auch noch einen Worker, der die Elemente in der Queue in Deiner Datei aktualisiert / überschreib.
Consumer / Producer Pattern oder SyncQueue <T> - Eine praktische Job-Queue könnte hier der richtige Weg sein.
Eine letzte Sache bleibt: welchen Grund gibt es, dass Du hier eine XML-Datei nutzt oder nutzen musst?
Wofür ist sie gut? Userverwaltung?
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Danke für deine lange Antwort.
Also bisher war mein Plan so.
if(!IsFileReadOnly(MapPath("test.xml");
{
File.SetAttributes(MapPath("test.xml"), FileAttributes.ReadOnly);
bearbeiten der XML
speichern der XML
File.SetAttributes(MapPath("test.xml"), FileAttributes.Normal);
}
else
{
System.Threading.Thread.Sleep(3000);
}
Also falls die Datei gesperrt ist warte ich einen Moment und versuche es erneut.
Der Grund für die XML ist die Geschwindigkeit beim laden im gegensatz zu einem mysql Zugriff. Sie besteht nur aus ca. 25 Reihen und das zwei User gleichzeitig drauf zugreifen passiert nur extrem seltend.
Für andere Anwendungen bei Doppelzugriff benutze ich auch mysql.
Wenn Du die Antworten der anderen liest, dann siehst Du, dass Du lieber einen FileStream nutzen sollst - oder eben eine Queue.
In meinen Augen ist ein Sleep() innerhalb eines Webrequests ein NoGo - egal ob 5ms oder 3000ms.
Der Vorschlag mit dem FileStream stammt aber eher auch nur daher, dass Du nicht gesagt hast, dass Du mit einer Webanwendung arbeitest. Denn Warten ist in der Web-Welt ein rotes Tuch.
Des weiteren kann man beim Zugriff über die Windows API (PInvoke) steuern, ob ein File gelockt ist oder nicht - aber auch davon würde ich abraten.
Du kannst Dir aber auch ein Caching über einen Singleton erstellen.
Hab ich in "Best Practice" für Rechte Caching Webseiten erklärt. Wie der Inhalt dieses Prinzips aussieht, ob hier ein XML oder ein SQL System, ob das nun Benutzerkonten oder andere Daten sind ist egal. Der Singleton sorgt dafür, dass es sauber funktioniert.
Was Du brauchst ist eine Synchronisierung - wie auch immer; ansonsten gehen Dir Daten flöten.
Einige - darunter meine - Fragen beantwortet und erklärt, was Du für ein System, ob Wenanwendung oder nicht, oder Umfeld hast, hast Du aber auch noch nicht.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo,
danke für eure Hilfe. Also es handelt sich um eine Webanwendung. Die Geschwindigkeit spricht für XML, da die Datei nur seltend verändert wird brauche ich auch eigentlich kein Datenbanksystem. In der XML werden nur ein paar Userspezifische Dinge gespeichert, wie ein paar Nutzungszeiten.
Das mit dem Warten ist bei meiner Webanwendung kein Problem, da es im Hintergrund stattfindet.