Open ilikerobots opened 2 years ago
Not sure how we could do this. The contract of box.put()
(and putMany()
) is that it sets the ID on the given object, if it was previously zero. This is especially important with relations (and relation cycles) so that when the related data is being put, the existing objects aren't reinserted always as new ones (that would result in an infinite recursion).
Ok, thanks. If I understand correctly,then, a project that uses objectbox and immutable models is required to fully manage IDs independently, right?
Do you think it would be possible to either use models that are mutable or immutable and they declare a function that transforms given instance with zero id to an instance with id generated by ObjectBox (which is then added to database)? So something like:
@Entity()
@freezed
class Book with _$Book {
factory Book({
@Id(assignBy: getBookWithId) @Default(0) int id,
}) = _Book;
}
Book getBookWithId(Book book, int id) => book.copyWith(id: id);
Using Equatable requires entity class to be immutable. This then require the Id field to be final, which currently is not supported. Please consider providing a way to update the entity as a whole with all fields as final. The solution suggested by @tomwyr is pointing in the right direction - not sure what side effects there would be.
@tomwyr - unfortunately that still won't satisfy the current "contract" of box.put()
(or putMany()
) which says it updates the given object. Besides this being possibly relied upon in client apps, it's also used when working with relations, requiring the relation target object instance to be updated with the inserted ID. Getting around this may require some more thought...
Anyone interested in this, please upvote the original issue (at the top) so the interest can be tracked when prioritizing development.
This works btw! ( note: this will make your properties mutable else everything will be same )
@Freezed(addImplicitFinal: false)
sealed class YourClass with _$YourClass {
@Entity(realClass: YourClass)
factory YourClass({
@Default(0) @Id() int localId,
@Unique() String? id,
}) = _YourClass;
}
In #229, the example supporting freezed entities uses assignable ids. Since freezed demands entities to be immutable, attempts to use value 0 ids fail in https://github.com/objectbox/objectbox-dart/blob/e587529f3a32ce7769e9a53a24ea4afafdd6d970/objectbox/lib/src/native/box.dart#L222 with error
Is it possible to use non-assignable ids with immutable entities currently? If not, would it be beneficial to make it so, e.g. by modifying the code above to use a copyWith or some other mechanism to set newly assigned ids?