Пример #1
0
        /// <summary>
        ///     Returns the Record at the specified Offset, while also updating Position to match.
        /// </summary>
        public BtrieveRecord GetRecord(uint offset)
        {
            Position = offset;

            if (_cache.TryGetValue(offset, out var record))
            {
                return(record);
            }

            using var cmd    = new SqliteCommand($"SELECT data FROM data_t WHERE id = {offset}", _connection);
            using var reader = cmd.ExecuteReader(System.Data.CommandBehavior.KeyInfo);
            try
            {
                if (!reader.Read())
                {
                    return(null);
                }

                using var stream = reader.GetStream(0);
                var data = new byte[stream.Length];
                stream.Read(data, 0, data.Length);

                record         = new BtrieveRecord(offset, data);
                _cache[offset] = record;
                return(record);
            }
            finally
            {
                reader.Close();
            }
        }
Пример #2
0
        /// <summary>
        ///     Inserts a new Btrieve Record.
        /// </summary>
        /// <return>Position of the newly inserted item, or 0 on failure</return>
        public uint Insert(byte[] record)
        {
            if (VariableLengthRecords && record.Length != RecordLength)
            {
                _logger.Warn($"Inserting variable length record of {record.Length} bytes into {FullPath}");
            }

            if (!VariableLengthRecords && record.Length != RecordLength)
            {
                _logger.Warn(
                    $"Btrieve Record Size Mismatch TRUNCATING. Expected Length {RecordLength}, Actual Length {record.Length}");
                record = ForceSize(record, RecordLength);
            }

            using var transaction = _connection.BeginTransaction();
            using var insertCmd   = new SqliteCommand()
                  {
                      Connection = _connection
                  };
            insertCmd.Transaction = transaction;

            if (!InsertAutoincrementValues(transaction, record))
            {
                transaction.Rollback();
                return(0);
            }

            var sb = new StringBuilder("INSERT INTO data_t(data, ");

            sb.Append(string.Join(", ", Keys.Values.Select(key => key.SqliteKeyName).ToList()));
            sb.Append(") VALUES(@data, ");
            sb.Append(string.Join(", ", Keys.Values.Select(key => $"@{key.SqliteKeyName}").ToList()));
            sb.Append(");");
            insertCmd.CommandText = sb.ToString();

            insertCmd.Parameters.AddWithValue("@data", record);
            foreach (var key in Keys.Values)
            {
                insertCmd.Parameters.AddWithValue($"@{key.SqliteKeyName}",
                                                  key.ExtractKeyInRecordToSqliteObject(record));
            }

            int queryResult;

            try
            {
                queryResult = insertCmd.ExecuteNonQuery();
            }
            catch (SqliteException ex)
            {
                _logger.Warn(ex, $"{FullPath}: Failed to insert record because {ex.Message}");
                transaction.Rollback();
                return(0);
            }

            var lastInsertRowId = Convert.ToUInt32(new SqliteCommand("SELECT last_insert_rowid()", _connection, transaction).ExecuteScalar());

            transaction.Commit();

            if (queryResult == 0)
            {
                return(0);
            }

            _cache[lastInsertRowId] = new BtrieveRecord(lastInsertRowId, record);
            return(lastInsertRowId);
        }
Пример #3
0
        /// <summary>
        ///     Updates the Record at the specified Offset.
        /// </summary>
        public bool Update(uint offset, byte[] recordData)
        {
            if (VariableLengthRecords && recordData.Length != RecordLength)
            {
                _logger.Warn($"Updating variable length record of {recordData.Length} bytes into {FullPath}");
            }

            if (!VariableLengthRecords && recordData.Length != RecordLength)
            {
                _logger.Warn(
                    $"Btrieve Record Size Mismatch. Expected Length {RecordLength}, Actual Length {recordData.Length}");
                recordData = ForceSize(recordData, RecordLength);
            }

            using var transaction = _connection.BeginTransaction();
            using var updateCmd   = new SqliteCommand()
                  {
                      Connection  = _connection,
                      Transaction = transaction
                  };

            if (!InsertAutoincrementValues(transaction, recordData))
            {
                transaction.Rollback();
                return(false);
            }

            var sb = new StringBuilder("UPDATE data_t SET data=@data, ");

            sb.Append(
                string.Join(", ", Keys.Values.Select(key => $"{key.SqliteKeyName}=@{key.SqliteKeyName}").ToList()));
            sb.Append(" WHERE id=@id;");
            updateCmd.CommandText = sb.ToString();

            updateCmd.Parameters.AddWithValue("@id", offset);
            updateCmd.Parameters.AddWithValue("@data", recordData);
            foreach (var key in Keys.Values)
            {
                updateCmd.Parameters.AddWithValue($"@{key.SqliteKeyName}",
                                                  key.ExtractKeyInRecordToSqliteObject(recordData));
            }

            int queryResult;

            try
            {
                queryResult = updateCmd.ExecuteNonQuery();
            }
            catch (SqliteException ex)
            {
                _logger.Warn(ex, $"Failed to update record because {ex.Message}");
                transaction.Rollback();
                return(false);
            }

            transaction.Commit();

            if (queryResult == 0)
            {
                return(false);
            }

            _cache[offset] = new BtrieveRecord(offset, recordData);
            return(true);
        }