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

函数应用中SQLite启动时数据丢失、关闭时数据保留问题排查

问题描述
  • 构建基于SQLite的Azure函数应用,包含数据插入功能
  • 使用func start启动应用并插入数据,Ctrl+C关闭后,在VSCode中可正常查询到数据
  • 再次启动应用时,所有数据被清空,推测是.db文件每次启动被重建导致数据丢失
相关代码

WeatherContext.cs

public partial class WeatherContext : DbContext
{
    public WeatherContext()
    {
        Database.EnsureCreated();
    }
    public WeatherContext(DbContextOptions<WeatherContext> options)
        : base(options)
    {
        
    }

    public DbSet<WeatherDays> WeatherDays{ get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connString = new SQLiteConnection(@"Data Source=weather.db;PRAGMA journal_mode=WAL;");
        var conn = new SQLiteConnection(connString);
        optionsBuilder.UseSqlite(conn);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<WeatherDays>(entity =>
        {
            entity.ToTable("WeatherDays");
            entity.Property(e => e.Id)
                .HasColumnName("id")
                .ValueGeneratedOnAdd();
            entity.Property(e => e.date)
                .HasColumnName("date")
                .HasMaxLength(255);
            entity.Property(e => e.temperature)
                .HasColumnName("temperature")
                .HasMaxLength(255);
            entity.Property(e => e.humidity)
                .HasColumnName("humidity")
                .HasMaxLength(255);
        }
        );

        OnModelCreatingPartial(modelBuilder);
    }
    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);

}

Startup.cs

[assembly: FunctionsStartup(typeof(WeatherApp.Startup))]
namespace WeatherApp
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<WeatherServices>();
            var connString = new SQLiteConnection(@"Data Source=weather.db;PRAGMA journal_mode=WAL;");
            var conn = new SQLiteConnection(connString);
            builder.Services.AddDbContext<WeatherContext>(options =>
              options.UseSqlite(conn)
            );

        }

    }
}
已尝试的解决方法
  • 将weather.db的输出属性设置为“较新则复制”和“始终复制”
  • 在连接字符串中添加;PRAGMA journal_mode=WAL;
解决方案

1. 移除无参构造函数中的Database.EnsureCreated()

Database.EnsureCreated()会在数据库不存在时创建,但函数应用启动时若意外触发无参构造,会导致数据库被重新初始化(甚至覆盖现有数据)。同时你已通过依赖注入配置DbContext,无需保留该逻辑:

public WeatherContext()
{
    // 移除 Database.EnsureCreated();
}

2. 修正连接字符串的传递方式

不要直接传入实例化的SQLiteConnection对象,改用连接字符串传入UseSqlite:

  • 修改WeatherContext.cs的OnConfiguring方法:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        var connString = @"Data Source=weather.db;PRAGMA journal_mode=WAL;";
        optionsBuilder.UseSqlite(connString);
    }
}
  • 修改Startup.cs中的配置:
public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddSingleton<WeatherServices>();
    var connString = @"Data Source=weather.db;PRAGMA journal_mode=WAL;";
    builder.Services.AddDbContext<WeatherContext>(options =>
      options.UseSqlite(connString)
    );
}

3. 指定数据库文件的绝对路径

函数应用启动时的工作目录可能不是项目根目录,导致每次启动创建新的数据库文件。改用绝对路径确保指向同一个文件:

var dbPath = Path.Combine(Environment.CurrentDirectory, "weather.db");
var connString = $"Data Source={dbPath};PRAGMA journal_mode=WAL;";

4. 调整数据库文件的复制属性

将weather.db的“复制到输出目录”设置为不复制,避免编译时覆盖运行目录中已存有数据的文件。

验证步骤
  1. 删除项目目录和运行目录下的旧weather.db文件
  2. 启动应用并插入测试数据
  3. 关闭应用,确认运行目录下的weather.db存有数据
  4. 再次启动应用,检查数据是否保留

内容的提问来源于stack exchange,提问作者Bryan Phan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:02:44