![]() | Editing files |
A class derived from EditFileManager must implement method OnCommit to state how the managed file should be edited.
In the following example, a file manager edits a document in XML format in case of a successfully committed transaction.
using System; using System.IO; using System.Linq; using System.Text; using System.Transactions; using System.Xml; using System.Xml.Linq; namespace Novacta.Transactions.IO.CodeExamples { /// <summary> /// Edits a file containing an XML document. /// </summary> public class EditXmlFileManager : EditFileManager { /// <summary> /// Initializes a new instance of the /// <see cref="EditXmlFileManager"/> class. /// </summary> /// <param name="path">The path of the managed file.</param> public EditXmlFileManager( string path) : base(path) { } /// <summary> /// Called when the transaction is successfully committed. /// </summary> /// <remarks> /// <para> /// This method looks for an <c>items</c> node and, /// if found, add a child <c>item</c> node having /// <c>0002</c> as its <c>id</c> and /// <c>A new item</c> as its <c>description</c>. /// </para> /// </remarks> protected override void OnCommit() { var document = XDocument.Load(this.ManagedFileStream); var items = from node in document.Descendants() where node.Name == "items" select node; var itemsNode = items.FirstOrDefault(); if (itemsNode != null) { XElement newItem = new XElement("item", new XElement("id", "0002"), new XElement("description", "A new item")); itemsNode.Add(newItem); } // Truncate the stream to delete the old content. this.ManagedFileStream.SetLength(0); var xmlTextWriter = new XmlTextWriter(this.ManagedFileStream, Encoding.UTF8); xmlTextWriter.Formatting = Formatting.Indented; document.Save(this.ManagedFileStream); } } public class EditFileManagerExample0 { public void Main() { // Define the XML document to be edited in case // of a successfully committed transaction. var document = new XDocument(); string content = "<?xml version='1.0' encoding='utf-8'?>" + "<items>" + "<item>" + "<id>0001</id>" + "<description>A mysterious item</description>" + "</item>" + "</items>"; document = XDocument.Parse(content); // Define the path for the file where // the document is saved. var managedPath = "edit-file-0.xml"; // Save the document in a file. // This will be edited in case of a // successfully committed transaction. using (FileStream stream = new FileStream(managedPath, FileMode.Create)) { document.Save(stream, SaveOptions.None); } // Create the manager. var manager = new EditXmlFileManager(managedPath); bool transactionSuccessfullyCommitted = true; try { // Create a TransactionScope to manage // your resources, such as files or database // connections. In this way, it is guaranteed // that the managing actions can commit or roll back // as a single unit of work. using (TransactionScope scope = new TransactionScope()) { // Enlist the manager. manager.EnlistVolatile(EnlistmentOptions.None); // Add here additional resource managers, // such as database connections, that need // enlisting in the current transaction. // The Complete method commits the transaction. // If an exception has been thrown, Complete // is not called and the transaction is rolled back. scope.Complete(); } } catch (Exception e) { Console.WriteLine("Transaction aborted."); Console.WriteLine("Reason:"); Console.WriteLine(e); transactionSuccessfullyCommitted = false; } finally { if (transactionSuccessfullyCommitted) { Console.WriteLine("Transaction successfully committed."); } } bool fileExists = File.Exists(managedPath); Console.WriteLine("File exists? {0}.", fileExists); if (fileExists) { // We want to access the managed file to inspect its // edited content, hence we need to dispose // its manager. manager.Dispose(); using (Stream stream = File.OpenRead(managedPath)) { XDocument savedDocument = XDocument.Load(stream); Console.WriteLine("File content:"); Console.WriteLine(savedDocument); } } } } } // Executing method Main() produces the following output: // // Transaction successfully committed. // File exists? True. // File content: // <items> // <item> // <id>0001</id> // <description>A mysterious item</description> // </item> // <item> // <id>0002</id> // <description>A new item</description> // </item> // </items>