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());
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
If you're creating a sandboxed macOS app use macosApplicationGroup
to
specify the application group. For more details see our online docs.
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.
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? fileMode,
int? maxReaders,
int? debugFlags,
bool queriesCaseSensitiveDefault = true,
String? macosApplicationGroup})
: _closesNativeStore = true,
_absoluteDirectoryPath =
path.context.canonicalize(_safeDirectoryPath(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');
}
final cStr = macosApplicationGroup.toNativeUtf8();
try {
C.posix_sem_prefix_set(cStr.cast());
} finally {
malloc.free(cStr);
}
}
_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));
final cStr = safeDirectoryPath.toNativeUtf8();
try {
checkObx(C.opt_directory(opt, cStr.cast()));
} finally {
malloc.free(cStr);
}
if (maxDBSizeInKB != null && maxDBSizeInKB > 0) {
C.opt_max_db_size_in_kb(opt, maxDBSizeInKB);
}
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) {
_reader.clear();
rethrow;
}
}