MAUI应用无法将图片二进制数据保存至SQLite数据库
问题概述
需求:通过文件选择器选择图片后,点击保存按钮将图片二进制数据存入名为gazouByte.db3的SQLite数据库;点击“获取全部图片列表”按钮时,在MainPage的CollectionView中显示已保存图片的Id、文件名及扩展名。
问题:图片二进制数据未存入数据库,点击获取列表按钮仅显示“got all file list”,无图片信息。已通过DB Browser for SQLite确认gazouByte表已创建,但无数据。
复现步骤
- 在Windows机器上用Visual Studio 2022启动调试;
- 点击“Select File”打开文件选择器,选择jpg/png格式图片;
- 确认“Select File”下方显示图片预览;
- 点击“Save File”按钮,确认显示“file saved”;
- 用DB Browser for SQLite查看数据库,表已创建但无数据。
相关代码
MainPage.xaml.cs
using WorkReview.Models; using System.Collections.Generic; using Microsoft.Maui.Controls; using WorkReview.ViewModels; using System.Runtime.CompilerServices; namespace WorkReview.Views { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new MainViewModel(); } public void OnGetAllGazouClicked(object sender, EventArgs args) { List<GazouByte> gazouByte = App.GazouByteRepo.GetAllGazouBytes(); statusMessage.Text = "got all file list"; } public void OnFileSaveClicked(object sender, EventArgs args) { (BindingContext as MainViewModel).SaveGazouToDataBase(); // 使用BindingContext实例调用Save方法 statusMessage.Text = "file saved"; } public async void OnFileSelectClicked(object sender, EventArgs args) { try { var result = await FilePicker.PickAsync(); var fileExtension = result.ContentType; var fileName = result.FileName; if (result != null) { if (result.FileName.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) || result.FileName.EndsWith("png", StringComparison.OrdinalIgnoreCase)) { using (var stream = await result.OpenReadAsync()) { using (var memoryStream = new MemoryStream())/// using语句:代码块执行完毕后自动释放资源 { await stream.CopyToAsync(memoryStream); // 将数据存入memoryStream后发送至ViewModel对应字段 (BindingContext as MainViewModel).gazouExtension = fileExtension; (BindingContext as MainViewModel).gazouName = fileName; (BindingContext as MainViewModel).gazouBinary = memoryStream.ToArray(); var previewStream = new MemoryStream(memoryStream.ToArray()); userPreview.Source = ImageSource.FromStream(() => previewStream); } } } else { statusMessage.Text = "不支持的文件类型。"; } } } catch (Exception ex) { statusMessage.Text = $"选择文件出错:{ex.Message}"; } } } }
GazouByteRepositry.cs
using SQLite; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WorkReview.Models; namespace WorkReview.Models { public class GazouByteRepositry { string _gazoudbPath; public string GazouStatusMessage { get; set; } private SQLiteConnection gazouconn; public GazouByteRepositry(string gazoudbPath) { _gazoudbPath = gazoudbPath; } private void Init() // 连接数据库后创建表 { if (gazouconn is not null) return; gazouconn = new SQLiteConnection(_gazoudbPath); gazouconn.CreateTable<GazouByte>(); } public void AddNewGazouByte(string gazouName, byte[] gazouBinary, string gazouExtension)// 将图片数据插入数据库 { ArgumentNullException.ThrowIfNull(gazouName, nameof(gazouExtension)); ArgumentNullException.ThrowIfNull(gazouBinary, nameof(gazouBinary)); ArgumentNullException.ThrowIfNull(gazouName, nameof(gazouName)); int gazouResult = 0; try { Init(); gazouResult = gazouconn.Insert(new GazouByte { GazouName = gazouName, GazouBinary = gazouBinary, GazouExtension = gazouExtension }); Console.WriteLine($"插入结果:{gazouResult}"); GazouStatusMessage = string.Format("已添加 {0} 条记录(文件名:{1})", gazouResult, gazouName); } catch (Exception ex) { GazouStatusMessage = string.Format("添加 {0} 失败。错误:{1}", gazouName, ex.Message); } } public List<GazouByte> GetAllGazouBytes()// 获取表数据并创建列表供MainPage的CollectionView使用 { try { Init(); return gazouconn.Table<GazouByte>().ToList(); } catch (Exception ex) { GazouStatusMessage = string.Format("检索数据失败。{0}", ex.Message); } return new List<GazouByte>(); } } }
GazouByte.cs
using SQLite; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CommunityToolkit; namespace WorkReview.Models; [Table("gazouByte")] public class GazouByte { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string GazouName { get; set; } public byte[] GazouBinary { get; set; } // 用于存储图片二进制数据 public string GazouExtension { get; set; } }
预期行为
- 调试启动时,在应用数据中创建
gazouByte表; - 选择图片后显示预览;
- 点击保存后图片数据存入数据库;
- 点击获取列表按钮,CollectionView显示图片的Id、文件名及扩展名。
已尝试操作
- 确认
GazouByteRepositry.AddNewGazouByte方法的异常处理逻辑正确; - 用DB Browser for SQLite确认表已创建;
- 发现未重新选图时再次点击保存按钮会触发
System.NullReferenceException。
环境信息
- Windows 11 Home 23H2
- Visual Studio Community 2022 Preview 17.11.0 Preview 4.0
- Microsoft.Maui.Controls 8.0.80
- Microsoft .NET SDK 8.0.107 (x64)
- SQlitePCLRaw.bundle_green 2.1.9
- sqlite-net-pcl 1.9.172
- CommunityToolkit.Mvvm 8.2.2
内容的提问来源于stack exchange,提问作者NTanaka
相关产品推荐
相关产品推荐

