You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用File.WriteAllBytes()创建的文件在程序结束后未保留

嵌入式SQLite数据库复制后目标路径无文件生成的问题

我跟着旧版sqlite-net-pcl教程操作,尝试用代码把嵌入式资源数据库复制到C://Users/我的用户/AppData/Local路径下,但程序运行结束后目标路径里没生成新文件。不过通过GetObject函数能确认数据库已正确复制,文件路径也没问题,是不是我对相关机制有根本性误解?


相关代码片段

MainPage.xaml.cs

using System.Collections.ObjectModel;
using System.Reflection;
using TestApp.Models;

namespace TestApp
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();

            var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
            using (Stream stream = assembly.GetManifestResourceStream("TestApp.Inventory.db"))
            {
                using (MemoryStream MemStr = new MemoryStream())
                {
                    stream.CopyTo(MemStr);
                    File.WriteAllBytes(ObjectRepository.DbPath, MemStr.ToArray());
                }
            }

            ObjectRepository repository = new ObjectRepository();
            foreach (var @object in repository.List())
            {
                Objects.Add(@object);
            }
         }
    }
}

ObjectRepository.cs

using System.Reflection;
using TestApp.Models;

namespace TestApp.Data
{
    public class ObjectRepository
    {
        private readonly SQLiteConnection _Database;

        public static string DbPath { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Inventory.db");

        public ObjectRepository()
        {
            _Database = new SQLiteConnection(DbPath);
            _Database.CreateTable<Object>();
        }
        public Object GetObject(string ObjectNumber)
        {
            return _Database.FindWithQuery<Object>("select * from Objects where ObjectNumber = ?", [ObjectNumber]);
        }
    }
}

TestApp/Models/Object.cs

using SQLite;

namespace TestApp.Models
{
    [Table("Objects")]
    public class Object
    {
        [PrimaryKey]
        public string ObjectNumber { get; set; } = string.Empty;
    }
}

问题原因及解决方案

1. SQLite自动创建空库的干扰

当你实例化SQLiteConnection时,如果指定路径的文件不存在,SQLite会自动创建一个空数据库文件。这会导致你产生误解:GetObject能正常执行不代表原嵌入式数据库的内容被复制,只是SQLite生成了空库,而非你期望的带数据的数据库。

2. 嵌入式资源读取可能失败

GetManifestResourceStream的参数必须是完整的资源全名(格式:[程序集名].[资源所在目录].[文件名]),如果资源路径写错,stream会为null,但后续SQLite的自动建库逻辑会掩盖这个错误。

可以通过以下代码验证资源名称是否正确:

var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
foreach (var resName in assembly.GetManifestResourceNames())
{
    Console.WriteLine(resName); // 输出所有嵌入式资源名称,找到你的数据库对应的正确名称
}

3. 未判断文件是否已存在

当前代码每次启动都会直接写入文件,但如果文件已存在,File.WriteAllBytes会直接覆盖。但更合理的逻辑是仅在文件不存在时复制,避免重复操作:

if (!File.Exists(ObjectRepository.DbPath))
{
    // 执行数据库复制逻辑
}

4. 路径验证错误

你手动查找的C://Users/我的用户/AppData/Local可能和Environment.SpecialFolder.LocalApplicationData实际指向的路径有差异,可以通过代码打印实际路径确认:

Console.WriteLine(ObjectRepository.DbPath); // 复制这个路径去查找文件

修正后的完整代码示例

MainPage.xaml.cs

using System.Collections.ObjectModel;
using System.Reflection;
using TestApp.Models;
using TestApp.Data;

namespace TestApp
{
    public partial class MainPage : ContentPage
    {
        public ObservableCollection<Object> Objects { get; set; } = new ObservableCollection<Object>();

        public MainPage()
        {
            InitializeComponent();
            BindingContext = this;

            EnsureDatabaseReady();

            ObjectRepository repository = new ObjectRepository();
            foreach (var @object in repository.List())
            {
                Objects.Add(@object);
            }
        }

        private void EnsureDatabaseReady()
        {
            if (File.Exists(ObjectRepository.DbPath))
            {
                Console.WriteLine("数据库已存在,跳过复制");
                return;
            }

            var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
            // 验证资源名称
            foreach (var resName in assembly.GetManifestResourceNames())
            {
                Console.WriteLine($"嵌入式资源:{resName}");
            }

            using (Stream stream = assembly.GetManifestResourceStream("TestApp.Inventory.db"))
            {
                if (stream == null)
                {
                    Console.WriteLine("未找到指定的嵌入式数据库资源");
                    return;
                }

                using (MemoryStream memStr = new MemoryStream())
                {
                    stream.CopyTo(memStr);
                    File.WriteAllBytes(ObjectRepository.DbPath, memStr.ToArray());
                    Console.WriteLine($"数据库已复制到:{ObjectRepository.DbPath}");
                }
            }
        }
    }
}

补充ObjectRepository的List方法

原代码中ObjectRepository缺少List()方法,需要补充实现:

public List<Object> List()
{
    return _Database.Table<Object>().ToList();
}

内容的提问来源于stack exchange,提问作者Frasher Gray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:57:03