如何在.NET MAUI中捕获Firebase的产品节点ID?
在.NET MAUI中使用firebase-database-dotnet获取Firebase节点Key的问题
我的Firebase数据结构如下:
products product1 category: "dairy" description: "Sliced Arequipe cheese, ideal for accompanying your meals." name: "Arequipe Cheese Sliced" price: 10.99 product10 category: "dairy" description: "Box of 30 Kikes eggs." name: "Kikes Eggs 30 pcs" price: 3.99
我在.NET MAUI里使用firebase-database-dotnet包操作Firebase,需要获取产品对应的节点Key(比如product1、product10)。但现有获取产品的方法仅返回产品对象,无法捕获节点Key:
public async Task<IEnumerable<T>> GetItemsAsync(bool forceRefresh = false) { try { var firebaseObjects = await _query .OnceAsync<T>(); return firebaseObjects .Select(x => x.Object); // 仅返回FirebaseObject<T>中的Object部分 } catch (Exception ex) { return null; } }
现在要实现保存选中产品的方法,需要拿到对应产品的节点ID,示例代码如下:
[RelayCommand] public async Task SaveProduct(Product product) { // 这里需要用GetItemsAsync获取现有产品,但如何捕获选中产品的节点ID(如'product1'或'product10')? }
想请教:
- 能否将节点ID包含在产品的数据表中?
- 这么做是否属于不良实践?
- 如何修改现有方法,同时获取节点Key和产品数据?
解决方案
1. 能否将节点ID存入数据表?是否为不良实践?
可以将节点ID存入数据表,但这属于不推荐的不良实践:
- Firebase节点Key本身就是唯一标识,重复存储会冗余占用存储空间;
- 若节点Key需要变更(虽场景极少),需同时更新节点Key与数据表中的ID,极易出现数据不一致;
- 从Firebase查询时,通过节点Key即可直接定位数据,无需在数据内重复存储。
2. 修改现有方法,同时获取节点Key与产品数据
有两种常用实现方式:
方式一:给Product类新增Id属性
首先在Product类中添加Id属性,用于存储节点Key:
public class Product { public string Id { get; set; } public string Category { get; set; } public string Description { get; set; } public string Name { get; set; } public double Price { get; set; } }
然后修改GetItemsAsync方法,将Firebase返回的FirebaseObject<T>的Key赋值给产品对象的Id属性:
public async Task<IEnumerable<T>> GetItemsAsync(bool forceRefresh = false) { try { var firebaseObjects = await _query.OnceAsync<T>(); return firebaseObjects.Select(x => { // 针对Product类型直接强转赋值 if (x.Object is Product product) { product.Id = x.Key; } // 通用场景可使用反射适配任意T类型 // var idProperty = typeof(T).GetProperty("Id"); // if (idProperty != null) idProperty.SetValue(x.Object, x.Key); return x.Object; }); } catch (Exception ex) { return null; } }
调用该方法后,每个Product对象的Id属性就对应Firebase的节点Key,在SaveProduct中直接使用product.Id即可获取节点ID。
方式二:返回包含Key和数据的自定义包装类
若不想修改Product类,可创建自定义类包装节点Key与产品数据:
public class FirebaseItem<T> { public string Key { get; set; } public T Data { get; set; } }
修改GetItemsAsync方法返回该自定义类型:
public async Task<IEnumerable<FirebaseItem<T>>> GetItemsAsync(bool forceRefresh = false) { try { var firebaseObjects = await _query.OnceAsync<T>(); return firebaseObjects.Select(x => new FirebaseItem<T> { Key = x.Key, Data = x.Object }); } catch (Exception ex) { return null; } }
在SaveProduct方法中,通过产品的唯一属性(如名称、价格)匹配对应的节点Key:
[RelayCommand] public async Task SaveProduct(Product product) { var allItems = await GetItemsAsync(); // 通过产品的唯一标识匹配对应节点Key var matchedItem = allItems.FirstOrDefault(item => item.Data.Name == product.Name && item.Data.Price == product.Price); if (matchedItem != null) { string productKey = matchedItem.Key; // 使用productKey执行后续保存逻辑 } }
内容的提问来源于stack exchange,提问作者Luis Julio
相关产品推荐
相关产品推荐

