public IDictionary <string, Stream> Export(IBinnerDb db) { const string delimiter = ","; const string lineBreak = "\r\n"; var streams = new Dictionary <string, Stream>(); var builder = new DataSetBuilder(); var dataSet = builder.Build(db); foreach (DataTable dataTable in dataSet.Tables) { var stream = new MemoryStream(); using (var writer = new StreamWriter(stream, Encoding.UTF8, 4096, true)) { foreach (DataRow row in dataTable.Rows) { var rowValues = new List <string>(); foreach (DataColumn col in dataTable.Columns) { rowValues.Add($"{EscapeValue(row[col], col.DataType)}"); } writer.Write($"{string.Join(delimiter, rowValues)}{lineBreak}"); } } streams.Add(dataTable.TableName, stream); } return(streams); }
private bool ValidateChecksum(IBinnerDb db) { var calculatedChecksum = BuildChecksum(db); if (db.Checksum.Equals(calculatedChecksum)) { return(true); } return(false); }
private string BuildChecksum(IBinnerDb db) { string hash; byte[] bytes = _serializer.Serialize(db, "Checksum"); using (var sha1 = new SHA1CryptoServiceProvider()) { hash = Convert.ToBase64String(sha1.ComputeHash(bytes)); } return(hash); }
public IDictionary <StreamName, Stream> Export(IBinnerDb db) { var streams = new Dictionary <StreamName, Stream>(); var builder = new DataSetBuilder(); var dataSet = builder.Build(db); var stream = new MemoryStream(); IWorkbook workbook = new XSSFWorkbook(); var styles = CreateStyles(workbook); foreach (DataTable table in dataSet.Tables) { ISheet sheet = workbook.CreateSheet(table.TableName); sheet.DefaultColumnWidth = 120; // insert header row var rowIndex = 0; IRow headerRow = sheet.CreateRow(rowIndex); rowIndex++; var columnIndex = 0; foreach (DataColumn dataColumn in table.Columns) { var c = headerRow.CreateCell(columnIndex); c.SetCellValue(dataColumn.ColumnName); c.CellStyle = styles["header"]; columnIndex++; } // insert all the row data for table foreach (DataRow dataRow in table.Rows) { IRow row = sheet.CreateRow(rowIndex); rowIndex++; columnIndex = 0; foreach (var value in dataRow.ItemArray) { SetCellValue(row.CreateCell(columnIndex), value, styles); columnIndex++; } } for (var i = 0; i < table.Columns.Count; i++) { sheet.AutoSizeColumn(i); } } workbook.Write(stream); var bytes = stream.ToArray(); stream.Dispose(); streams.Add(new StreamName("BinnerParts", "xlsx"), new MemoryStream(bytes, false)); return(streams); }
/// <summary> /// Build a dataset from an IBinnerDb object /// </summary> /// <param name="db"></param> /// <returns></returns> public DataSet Build(IBinnerDb db) { var dataSet = new DataSet("Datset"); var partsTable = new DataTable("Parts"); var partTypesTable = new DataTable("PartTypes"); dataSet.Locale = partsTable.Locale = partTypesTable.Locale = Thread.CurrentThread.CurrentCulture; dataSet.Tables.Add(partsTable); dataSet.Tables.Add(partTypesTable); // build the Parts table schema var partType = typeof(Part).GetExtendedType(); foreach (var prop in partType.Properties) { partsTable.Columns.Add(prop.Name, prop.Type); } // build the PartTypes table schema var partTypesType = typeof(PartType).GetExtendedType(); foreach (var prop in partTypesType.Properties) { partTypesTable.Columns.Add(prop.Name, prop.Type); } // populate the Parts table foreach (var part in db.Parts) { var row = partsTable.NewRow(); foreach (var prop in partType.Properties) { row[prop.Name] = part.GetPropertyValue(prop); } partsTable.Rows.Add(row); } // populate the PartTypes table foreach (var part in db.PartTypes) { var row = partTypesTable.NewRow(); foreach (var prop in partTypesType.Properties) { row[prop.Name] = part.GetPropertyValue(prop); } partTypesTable.Rows.Add(row); } return(dataSet); }
public IDictionary <string, Stream> Export(IBinnerDb db) { var streams = new Dictionary <string, Stream>(); var builder = new DataSetBuilder(); var dataSet = builder.Build(db); var stream = new MemoryStream(); using (var writer = new StreamWriter(stream, Encoding.UTF8, 4096, true)) { DataSetHelper.CreateWorkbook(stream, dataSet); } streams.Add("BinnerParts", stream); return(streams); }
protected virtual void Dispose(bool isDisposing) { if (_isDisposed) { return; } if (isDisposing) { // obtain the lock before removing it _dataLock.Wait(); try { _quitEvent.Set(); if (!_ioThread.Join(5000)) { _ioThread.Abort(); } if (_isDirty) { Task.Run(async() => { await SaveDatabaseAsync(false); }).GetAwaiter().GetResult(); } _ioThread = null; _quitEvent.Dispose(); _quitEvent = null; _db = null; } finally { _dataLock.Release(); _dataLock.Dispose(); _dataLock = null; } } _isDisposed = true; }
/// <summary> /// Load the database from disk /// </summary> /// <param name="requireLock">True if a lock needs to be acquired before saving</param> /// <returns></returns> private async Task LoadDatabaseAsync(bool requireLock = true) { if (File.Exists(_config.Filename)) { if (requireLock) { await _dataLock.WaitAsync(); } try { using (var stream = File.OpenRead(_config.Filename)) { var dbVersion = ReadDbVersion(stream); // copy the rest of the bytes var bytes = new byte[stream.Length - stream.Position]; stream.Read(bytes, 0, bytes.Length); _db = LoadDatabaseByVersion(dbVersion, bytes); bytes = null; // could make this non-fatal if (!ValidateChecksum(_db)) { throw new Exception("The database did not pass validation! It is either corrupt or has been modified outside of the application."); } _primaryKeyTracker = new PrimaryKeyTracker(new Dictionary <string, long> { // there is no guaranteed order so we must sort first { typeof(Part).Name, _db.Parts.OrderByDescending(x => x.PartId).Select(x => x.PartId).FirstOrDefault() }, { typeof(PartType).Name, _db.PartTypes.OrderByDescending(x => x.PartTypeId).Select(x => x.PartTypeId).FirstOrDefault() }, }); } } catch (Exception ex) { throw new Exception("Failed to load database!", ex); } finally { if (requireLock) { _dataLock.Release(); } } } else { if (requireLock) { await _dataLock.WaitAsync(); } try { _db = NewDatabase(); } finally { if (requireLock) { _dataLock.Release(); } } } }