函数应用中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的“复制到输出目录”设置为不复制,避免编译时覆盖运行目录中已存有数据的文件。
验证步骤
- 删除项目目录和运行目录下的旧
weather.db文件 - 启动应用并插入测试数据
- 关闭应用,确认运行目录下的
weather.db存有数据 - 再次启动应用,检查数据是否保留
内容的提问来源于stack exchange,提问作者Bryan Phan
相关产品推荐
相关产品推荐

