Xamarin Forms中SQLite跨模型数据访问异常求助
Xamarin Forms SQLite关联数据存储与读取问题解决方案
问题描述
我在使用SQLite开发Xamarin Forms项目时遇到以下问题:
- 在新增Item页面创建Item实例并关联Priority模型,点击保存后调试时能获取到包含Priority的完整数据
- 但SQLite数据库中Item表的ItemPriority字段仅显示
{CrudTasks.Models.Priority} - 在列表页访问该关联数据时无响应
相关代码
保存Item的方法
private async void ExecuteSaveItemsCommand() { try { Item itemSaved = new Item { Name = NameSave, Description = DescriptionSave, ItemPriority = new Priority() { PriorityName = PrioritySave, PriorityColor = "#ccc" } }; _itemsService.InsertItem(itemSaved); ExecuteBackProductPageCommand(); } catch (Exception ex) { await Shell.Current.DisplayAlert("Error", ex.Message, "OK"); } }
Item模型
namespace CrudTarefas.Models { [Table("Items")] public class Item { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } [ManyToOne] public Priority ItemPriority { get; set; } } }
Priority模型
namespace CrudTarefas.Models { [Table("Priorities")] public class Priority { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string PriorityName { get; set; } public string PriorityColor { get; set; } } }
列表页CollectionView布局
<ScrollView VerticalScrollBarVisibility="Never"> <StackLayout> <CollectionView ItemsSource="{Binding ItemsList}"> <CollectionView.ItemsLayout> <LinearItemsLayout ItemSpacing="20" Orientation="Vertical" /> </CollectionView.ItemsLayout> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout> <Grid Margin="0,0,0,20" Padding="10" xct:CornerRadiusEffect.CornerRadius="12" BackgroundColor="{Binding ItemPriority.PriorityColor}" RowDefinitions="*,20,20" RowSpacing="10"> <Frame Grid.Row="0" Padding="5" HorizontalOptions="Start"> <Label Text="{Binding ItemPriority.PriorityName}" /> </Frame> <Label Grid.Row="1" Text="{Binding Name}" TextColor="Black" /> <Label Grid.Row="2" Text="{Binding Description}" TextColor="Black" /> </Grid> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </StackLayout> </ScrollView>
列表页ViewModel代码
#region constructor public ListItemsViewmodel(INavigation navigation) { Navigation = navigation; _itemsService = new ItemsService(); LoadItems(); GoAddItemPageCommand = new Command(ExecuteGoAddItemPageCommand); LoadItemsCommand = new Command(ExecuteLoadItemsCommand); } #endregion #region commands public ICommand GoAddItemPageCommand { get; set; } public ICommand LoadItemsCommand { get; set; } #endregion #region methods private void LoadItems() { var items = _itemsService.GetAllItems(); ItemsList = new ObservableCollection<Item>(items); } #endregion
问题原因分析
- SQLite-net仅声明
[ManyToOne]属性无法自动处理关联关系,需要配合外键字段存储子对象的ID - 保存时未先存储子对象(Priority),导致Item无法关联到有效的Priority记录
- 读取数据时未主动加载关联的子对象,导致列表页无法获取Priority的具体数据
解决方案
1. 修改Item模型,添加外键字段
在Item类中新增外键字段,并配置ManyToOne关联的外键映射:
namespace CrudTarefas.Models { [Table("Items")] public class Item { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } // 新增外键字段,存储Priority的ID public int PriorityId { get; set; } // 配置ManyToOne关联,指定关联的外键字段 [ManyToOne(nameof(PriorityId))] public Priority ItemPriority { get; set; } } }
2. 调整保存逻辑,先存Priority再存Item
需要先将Priority保存到数据库获取自增ID,再关联到Item的外键字段:
private async void ExecuteSaveItemsCommand() { try { // 先创建并保存Priority var priority = new Priority() { PriorityName = PrioritySave, PriorityColor = "#ccc" }; // 确保已实现PriorityService的Insert方法 _priorityService.InsertPriority(priority); // 创建Item并关联Priority的ID Item itemSaved = new Item { Name = NameSave, Description = DescriptionSave, PriorityId = priority.Id, ItemPriority = priority }; _itemsService.InsertItem(itemSaved); ExecuteBackProductPageCommand(); } catch (Exception ex) { await Shell.Current.DisplayAlert("Error", ex.Message, "OK"); } }
3. 修改读取逻辑,加载关联数据
在获取Item列表时,使用WithChildren()方法自动加载关联的Priority对象:
// 在ItemsService的GetAllItems方法中修改 public List<Item> GetAllItems() { using (var conn = new SQLiteConnection(_dbPath)) { // 加载关联的Priority子对象 return conn.Table<Item>().WithChildren().ToList(); } }
4. 更新数据库结构
修改模型后,删除旧的数据库文件(测试环境),让SQLite自动生成包含PriorityId字段的新表结构;生产环境需执行数据库迁移。
内容的提问来源于stack exchange,提问作者Sergio Gabriel
相关产品推荐
相关产品推荐

