Store constructor
Creates a BoxStore using the model definition from your
objectbox.g.dart
file in the given directory
path
(or if null the defaultDirectoryPath).
For example in a Flutter app:
getApplicationDocumentsDirectory().then((dir) {
_store = Store(getObjectBoxModel(), directory: dir.path + "/objectbox");
});
Or for a Dart app:
final store = Store(getObjectBoxModel());
In-memory database
To use a file-less in-memory database, instead of a directory path pass
inMemoryPrefix together with an identifier string as the directory
:
final inMemoryStore =
Store(getObjectBoxModel(), directory: "${Store.inMemoryPrefix}test-db");
Case insensitive queries
By default, ObjectBox queries are case sensitive. Set queriesCaseSensitiveDefault
to false
to make queries ignore case by default.
Case sensitivity can also be set for each query.
macOS application group
When creating a sandboxed macOS app use macosApplicationGroup
to
specify the application group. See the info boxes on the
Getting Started page for
details.
Note: due to limitations in macOS this must be 19 characters or shorter.
Maximum database size
maxDBSizeInKB
sets the maximum size the database file can grow to.
When applying a transaction (e.g. putting an object) would exceed it a
DbFullException is thrown.
By default, this is 1 GB, which should be sufficient for most applications. In general, a maximum size prevents the database from growing indefinitely when something goes wrong (for example data is put in an infinite loop).
This value can be changed, so increased or also decreased, each time when opening a store.
Maximum data size
maxDataSizeInKB
sets the maximum size the data stored in the database
can grow to. When applying a transaction (e.g. putting an object) would
exceed it a DbMaxDataSizeExceededException is thrown.
Must be below maxDBSizeInKB
.
Different from maxDBSizeInKB
this only counts bytes stored in objects,
excluding system and metadata. However, it is more involved than database
size tracking, e.g. it stores an internal counter. Only use this if a
stricter, more accurate limit is required.
When the data limit is reached, data can be removed to get below the limit again (assuming the database size limit is not also reached).
File mode
Specify unix-style file permissions
for database files with fileMode
. E.g. for -rw-r----
(owner, group,
other) pass the octal code 0640
. Any newly generated directory
additionally gets searchable (01) for groups with read or write permissions.
It's not allowed to pass in an executable flag.
Maximum number of readers
maxReaders
sets the maximum number of concurrent readers. For most
applications, the default is fine (about 126 readers).
A "reader" is short for a thread involved in a read transaction. If the maximum is exceeded the store throws DbMaxReadersExceededException. In this case check that your code only uses a reasonable amount of threads.
For highly concurrent setups (e.g. you are using ObjectBox on the server side) it may make sense to increase the number.
Note: Each thread that performed a read transaction and is still alive holds on to a reader slot. These slots only get vacated when the thread ends. Thus, be mindful with the number of active threads.
Debug flags
Pass one or more DebugFlags to debugFlags
to enable debug log
output:
final store = Store(getObjectBoxModel(),
debugFlag: DebugFlags.logQueries | DebugFlags.logQueryParameters);
See our examples for more details.
Implementation
Store(ModelDefinition modelDefinition,
{String? directory,
int? maxDBSizeInKB,
int? maxDataSizeInKB,
int? fileMode,
int? maxReaders,
int? debugFlags,
bool queriesCaseSensitiveDefault = true,
String? macosApplicationGroup})
: _closesNativeStore = true,
_absoluteDirectoryPath = _safeAbsoluteDirectoryPath(directory) {
try {
if (Platform.isMacOS && macosApplicationGroup != null) {
if (!macosApplicationGroup.endsWith('/')) {
macosApplicationGroup += '/';
}
if (macosApplicationGroup.length > 20) {
ArgumentError.value(macosApplicationGroup, 'macosApplicationGroup',
'Must be at most 20 characters long');
}
withNativeString(macosApplicationGroup, C.posix_sem_prefix_set);
}
_checkStoreDirectoryNotOpen();
final model = Model(modelDefinition.model);
final safeDirectoryPath = _safeDirectoryPath(directory);
final opt = C.opt();
checkObxPtr(opt, 'failed to create store options');
try {
checkObx(C.opt_model(opt, model.ptr));
checkObx(withNativeString(
safeDirectoryPath, (cStr) => C.opt_directory(opt, cStr)));
if (maxDBSizeInKB != null && maxDBSizeInKB > 0) {
C.opt_max_db_size_in_kb(opt, maxDBSizeInKB);
}
if (maxDataSizeInKB != null && maxDataSizeInKB > 0) {
C.opt_max_data_size_in_kb(opt, maxDataSizeInKB);
}
if (fileMode != null && fileMode >= 0) {
C.opt_file_mode(opt, fileMode);
}
if (maxReaders != null && maxReaders > 0) {
C.opt_max_readers(opt, maxReaders);
}
if (debugFlags != null) {
C.opt_debug_flags(opt, debugFlags);
}
} catch (e) {
C.opt_free(opt);
rethrow;
}
if (debugLogs) {
print(
"Opening store (C lib V${libraryVersion()})... path=$safeDirectoryPath"
" isOpen=${isOpen(safeDirectoryPath)}");
}
_cStore = C.store_open(opt);
_checkStorePointer(_cStore);
// Always create _reference, so it can be non-nullable.
// Ensure we only try to access the store created in the same process.
// Also serves as a simple sanity check/hash.
_reference = ByteData(2 * _int64Size);
_reference.setUint64(0 * _int64Size, pid);
_reference.setUint64(1 * _int64Size, _ptr.address);
_openStoreDirectories.add(_absoluteDirectoryPath);
_attachConfiguration(_cStore, modelDefinition, safeDirectoryPath,
queriesCaseSensitiveDefault);
_attachFinalizer();
} catch (e) {
_readPointers.clear();
rethrow;
}
}