/// <summary> /// Flush unsaved changes. /// </summary> /// <remarks> /// If the number of items is zero, the file is deleted from disk. /// If saving over existing file it first gets deleted and the saved. Deletion and addition are reported to the corresponding /// file container browser to synchronise the files collection. Any discrepancies (like when deleting existing and not finding it /// on disk or in the file container's collection result in an exception. Data access should be stopped as soon as possible /// to prevent data corruption in such cases. /// The collection of data items is sorted if necessary if <see cref="OverrideMode" /> is OFF. Otherwise the caller is /// responsible for sorting the collection (may call <see cref="Sort()" /> when necessary). /// </remarks> /// <exception cref="FileContainerNotificationException"> /// The file cannot be found in the container; possible concurrency issue /// </exception> /// <exception cref="OverlappingFileInContainer"> /// The <paramref name="newRepoFile"/> overlaps with an existing file; possible concurrency issue or internal error. /// </exception> public void Flush() { using (var scope = StorageTransactionScope.Create(_folder.Repository)) { FlushImpl(); scope.Complete(); } }
/// <summary> /// Force save to disk. /// </summary> public void Save() { RepositoryFolder.CheckNotDetached(_folder); using (var scope = StorageTransactionScope.Create(_folder.Repository)) { _folderConfig.Save(this.ConfigFilePath, this.FileProvider); scope.Complete(); } }
/// <summary> /// Delete properties from disk. /// </summary> public void Delete() { RepositoryFolder.CheckNotDetached(_folder); using (var scope = StorageTransactionScope.Create(_folder.Repository)) { if (ConfigFileExists) { this.FileProvider.Delete(this.ConfigFilePath); } scope.Complete(); } }
/// <summary> /// Create scope which will not create its own transaction, but would only pick up existing ambient transaction. /// </summary> /// <param name="repository"> /// Repository /// </param> /// <param name="pendingTransaction"> /// Pending transaction to reuse if not <see langword="null"/>. /// </param> /// <returns> /// New transaction scope not owning a transaction. /// </returns> /// <remarks> /// /// </remarks> /// <exception cref="InvalidOperationException"> /// Current transactional context is inconsistent with the <paramref name="pendingTransaction"/>. /// </exception> /// <remarks> /// When <paramref name="pendingTransaction"/> is not null the ambient transaction must be: /// - null /// - equal to <paramref name="pendingTransaction"/> /// - belong to the same master transaction /// Otherwise the "always start new transaction" option must be ON (<see cref="IRepositoryManager.Settings.StorageTransactionSettings"/>). /// If top level scope is created lazy and it is not NULL scope then there is external transaction being used in repository. /// </remarks> public static StorageTransactionScope CreateLazy(IRepository repository, IFileSystemTransaction pendingTransaction) { StorageTransactionScope retval; if (pendingTransaction == null) { retval = new StorageTransactionScope(repository: repository, disposeIfSlave: false, okToStartOwnTransaction: false); // proxy may have to be a new transaction instance, but slave of an existing managed transaction Check.Ensure(!retval.IsTransactionOwner, "Lazy scope must not create and own a transaction, it can only be a proxy to an existing transaction."); } else { CheckContextForPendingTransaction(repository: repository, pendingTransaction: pendingTransaction); retval = Create(repository, pendingTransaction); Check.Ensure(pendingTransaction == retval.UnderlyingTransaction); } Check.Ensure(!retval.ToBeDisposed, "Lazy scope must not own or dispose underlying transaction"); return(retval); }