我有一个关于 flutter 领域数据库的问题,我想在本地使用。
背景:从realm数据库读取的对象由realm数据库管理=>object.isManaged = true。如果我在这里使用数据层和域层并转换域类型中的对象,更改属性并转换回数据类型,则对象现在是非托管的 => object.isManaged = false。所以我不能再删除和更改数据库中的对象。删除时出现以下错误:“领域错误:无法删除非托管对象”。
问题:是否有一个实用的解决方案 - 不放弃不同的层(数据和域)?
提前致谢。
我想如果我能确保数据已经是真实数据库的一部分,我应该能够强制对象为 object.isManaged = true。或者我可以创建一个托管对象,而无需对数据库本身进行新的访问。
我添加了一张图片作为进一步的解释。我的目标是在 Presentation / UI 层中不依赖于 Realm。
这里是领域模型的模型:
class ShoppingListItem {
String uuid;
int amount;
bool done;
Grocery grocery;
ShoppingListItem({
required this.uuid,
required this.amount,
required this.done,
required this.grocery,
});
}
class Grocery {
int? barcode;
String? name;
String? brand;
Grocery({
this.barcode,
this.name,
this.brand,
});
}
来自数据层的模型也用于 Realm
@RealmModel()
class _ShoppingListItemData {
@PrimaryKey()
late String uuid;
late int? amount;
late bool? done;
late _GroceryData? grocery;
}
@RealmModel(ObjectType.embeddedObject)
class _GroceryData {
late int? barcode;
late String? name;
late String? brand;
}
这里是将数据转换为数据并返回到域的方法
class Interface {
static ShoppingListItem toDomain(ShoppingListItemData shoppingListItemData) {
return ShoppingListItem(
uuid: shoppingListItemData.uuid,
amount: shoppingListItemData.amount ?? 1,
done: shoppingListItemData.done ?? false,
grocery: Grocery(
barcode: shoppingListItemData.grocery?.barcode ?? 0,
name: shoppingListItemData.grocery?.name));
}
static ShoppingListItemData fromDomain(ShoppingListItem shoppingListItem) {
return ShoppingListItemData(shoppingListItem.uuid,
amount: shoppingListItem.amount,
done: shoppingListItem.done,
grocery: GroceryData(
barcode: shoppingListItem.grocery.barcode,
brand: shoppingListItem.grocery.brand,
name: shoppingListItem.grocery.name));
}
}
一旦数据被复制到域,然后又复制回数据层,object.isManaged = false因此无法应用对领域数据库的删除或修改。
是的,您是正确的,将对象转换为域类型然后再转换回数据类型会导致无法从 Realm 数据库中删除的非托管对象。一种可能的解决方案是使用一种单独的方法来更新数据库中的托管对象,而不是将它们转换为非托管对象。例如,您可以在数据层中创建一个单独的方法,用域层提供的新值更新数据库中现有的托管对象。此方法会将托管对象作为输入参数并更新其属性,然后将更改保存到数据库中。这是一个如何修改代码以实现此目的的示例:
class Interface {
static ShoppingListItem toDomain(ShoppingListItemData shoppingListItemData) {
return ShoppingListItem(
uuid: shoppingListItemData.uuid,
amount: shoppingListItemData.amount ?? 1,
done: shoppingListItemData.done ?? false,
grocery: Grocery(
barcode: shoppingListItemData.grocery?.barcode ?? 0,
name: shoppingListItemData.grocery?.name));
}
static void update(ShoppingListItemData shoppingListItemData, ShoppingListItem shoppingListItem) {
shoppingListItemData.amount = shoppingListItem.amount;
shoppingListItemData.done = shoppingListItem.done;
if (shoppingListItemData.grocery == null) {
shoppingListItemData.grocery = _GroceryData();
}
shoppingListItemData.grocery?.barcode = shoppingListItem.grocery.barcode;
shoppingListItemData.grocery?.name = shoppingListItem.grocery.name;
// save the changes to the database
shoppingListItemData.realm!.write(() {
shoppingListItemData.realm!.add(shoppingListItemData, update: true);
});
}
static ShoppingListItemData fromDomain(ShoppingListItem shoppingListItem) {
var shoppingListItemData = ShoppingListItemData(shoppingListItem.uuid,
amount: shoppingListItem.amount,
done: shoppingListItem.done,
grocery: GroceryData(
barcode: shoppingListItem.grocery.barcode,
brand: shoppingListItem.grocery.brand,
name: shoppingListItem.grocery.name));
// mark the object as managed
shoppingListItemData.isManaged = true;
return shoppingListItemData;
}
}
在本例中,update方法将一个
ShoppingListItemData
对象作为第一个参数,该对象是Realm数据库中的一个托管对象。然后它使用 ShoppingListItem
对象提供的新值更新对象的属性,并将更改保存到数据库中。请注意,我们在将对象从领域层转换为数据层之后还设置了shoppingListItemData.isManaged = true
。使用这种方法,您可以保留单独的数据层和域层,同时仍然能够更新数据库中的托管对象。