///<summary>Saves changes in the tables to the database.</summary> public void WriteData(DbConnection connection, IProgressReporter progress) { progress = progress ?? new EmptyProgressReporter(); progress.Caption = "Saving database"; progress.Maximum = Tables.Sum(t => t.Changes.Count); using (var transactionContext = new TransactionContext(connection)) { foreach (var table in Tables.SortDependencies(ts => ts.Table.Schema)) { if (progress.WasCanceled) { return; } table.WriteChanges(transactionContext, RowChangeType.Added, progress.ChildOperation()); } foreach (var table in Tables.SortDependencies(ts => ts.Table.Schema)) { if (progress.WasCanceled) { return; } table.WriteChanges(transactionContext, RowChangeType.Changed, progress.ChildOperation()); } foreach (var table in Tables.SortDependencies(ts => ts.Table.Schema).Reverse()) { if (progress.WasCanceled) { return; } table.WriteChanges(transactionContext, RowChangeType.Removed, progress.ChildOperation()); } if (progress.WasCanceled) { return; } transactionContext.Commit(); } //If we didn't get an exception, clear the changes. //If we did, don't clear, since we didn't commit it foreach (var table in Tables) { table.ClearChanges(); } }
///<summary>Downloads the update and extracts its files to a temporary directory.</summary> ///<param name="existingFiles">The path to the existing files that should be updated. /// Any files in this directory that match files in the update will not be re-downloaded.</param> ///<param name="organizationId">The organization ID to match organization-specific directories (see <see cref="OrganizationDirectoryPattern"/>).</param> ///<param name="ui">An optional IProgressReporter implementation to report the progress of the download.</param> ///<returns>The path to the extracted files.</returns> public string DownloadFiles(string existingFiles, string organizationId, IProgressReporter ui) { if (!Directory.Exists(existingFiles)) { throw new DirectoryNotFoundException(existingFiles + " does not exist"); } ui = ui ?? new EmptyProgressReporter(); ui.CanCancel = true; var path = Path.GetTempFileName(); File.Delete(path); Directory.CreateDirectory(path); try { var newFiles = Files // Extract files from this organization to the root .Select(f => organizationId == null ? f : f.StripPrefix(OrganizationPrefix + organizationId + "\\")) // Skip other organization directories .Where(f => !OrganizationDirectoryPattern.IsMatch(f.RelativePath)) .Where(f => !f.Matches(existingFiles)) .ToList(); ui.Maximum = newFiles.Sum(f => f.Length); foreach (var file in newFiles) { ui.Caption = "Downloading " + file.RelativePath; file.DownloadFile(path, ui.ChildOperation()); if (ui.WasCanceled) { Directory.Delete(path, true); return(null); } } } catch (Exception ex) { Directory.Delete(path, true); if (ui.WasCanceled) { return(null); //If it was canceled, we'll get a CryptoException because the CryptoStream was closed } throw new UpdateErrorException(ex); } return(path); }
void UploadFiles(IProgressReporter ui) { ui.Maximum = newFiles.Sum(uf => uf.Length); foreach (var file in newFiles) { ui.Caption = "Uploading " + file.RelativePath; var ftpRequest = FtpClient.Default.CreateRequest(Combine(UpdateConfig.Standard.RemotePath, file.RemoteUrl)); ftpRequest.Method = WebRequestMethods.Ftp.UploadFile; using (var transform = UpdateChecker.CreateFileEncryptor()) using (var requestStream = ftpRequest.GetRequestStream()) using (var encryptingStream = new CryptoStream(requestStream, transform, CryptoStreamMode.Write)) using (var zipper = new GZipStream(encryptingStream, CompressionMode.Compress, true)) using (var fileStream = File.Open(Path.Combine(basePath, file.RelativePath), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { fileStream.CopyTo(zipper, file.Length, ui.ChildOperation()); } ftpRequest.GetResponse().Close(); } }
///<summary>Downloads the update and extracts its files to a temporary directory.</summary> ///<param name="existingFiles">The path to the existing files that should be updated. /// Any files in this directory that match files in the update will not be re-downloaded.</param> ///<param name="organizationId">The organization ID to match organization-specific directories (see <see cref="OrganizationDirectoryPattern"/>).</param> ///<param name="ui">An optional IProgressReporter implementation to report the progress of the download.</param> ///<returns>The path to the extracted files.</returns> public string DownloadFiles(string existingFiles, string organizationId, IProgressReporter ui) { if (!Directory.Exists(existingFiles)) throw new DirectoryNotFoundException(existingFiles + " does not exist"); ui = ui ?? new EmptyProgressReporter(); ui.CanCancel = true; var path = Path.GetTempFileName(); File.Delete(path); Directory.CreateDirectory(path); try { var newFiles = Files // Extract files from this organization to the root .Select(f => organizationId == null ? f : f.StripPrefix(OrganizationPrefix + organizationId + "\\")) // Skip other organization directories .Where(f => !OrganizationDirectoryPattern.IsMatch(f.RelativePath)) .Where(f => !f.Matches(existingFiles)) .ToList(); ui.Maximum = newFiles.Sum(f => f.Length); foreach (var file in newFiles) { ui.Caption = "Downloading " + file.RelativePath; file.DownloadFile(path, ui.ChildOperation()); if (ui.WasCanceled) { Directory.Delete(path, true); return null; } } } catch (Exception ex) { Directory.Delete(path, true); if (ui.WasCanceled) return null; //If it was canceled, we'll get a CryptoException because the CryptoStream was closed throw new UpdateErrorException(ex); } return path; }