SQLite多表存储异常:批量保存通话记录仅最后一条生效
问题排查与解决方案
1. 检查SqlHelper中SQLiteConnection的复用逻辑
如果你的SqlHelper复用同一个SQLiteConnection实例,且插入操作时未正确重置参数,会导致参数被覆盖,最终只有最后一条数据插入成功。
- 修正方案:确保每次插入操作使用独立的
SQLiteCommand实例,或在循环前清空参数集合// 错误示例:复用command未重置参数 var command = connection.CreateCommand(); command.CommandText = "INSERT INTO CallHistory (Id, Number, Duration) VALUES (@Id, @Number, @Duration)"; foreach(var record in records) { command.Parameters.AddWithValue("@Id", record.Id); // 未移除旧参数,多次循环后参数累积覆盖,仅最后一次生效 command.ExecuteNonQuery(); } // 正确示例:每次循环创建新command foreach(var record in records) { using(var command = connection.CreateCommand()) { command.CommandText = "INSERT INTO CallHistory (Id, Number, Duration) VALUES (@Id, @Number, @Duration)"; command.Parameters.AddWithValue("@Id", record.Id); command.Parameters.AddWithValue("@Number", record.Number); command.Parameters.AddWithValue("@Duration", record.Duration); command.ExecuteNonQuery(); } }
2. 启用事务处理优化批量插入
批量插入未使用事务不仅效率低下,还可能因隐式的连接状态问题导致数据丢失。同时事务能保证操作的原子性:
using(var connection = new SQLiteConnection("Data Source=your_local.db")) { connection.Open(); using(var transaction = connection.BeginTransaction()) { try { foreach(var record in records) { using(var command = connection.CreateCommand()) { command.Transaction = transaction; command.CommandText = "INSERT INTO CallHistory (Id, Number, Duration) VALUES (@Id, @Number, @Duration)"; command.Parameters.AddWithValue("@Id", record.Id); command.Parameters.AddWithValue("@Number", record.Number); command.Parameters.AddWithValue("@Duration", record.Duration); command.ExecuteNonQuery(); } } transaction.Commit(); } catch(Exception ex) { transaction.Rollback(); throw; } } }
3. 验证实体类与表结构的映射
如果使用ORM框架(如SQLite-net),检查通话记录实体的主键设置:
- 若所有记录使用相同的主键值,插入时会覆盖之前的数据
- 修正方案:将主键设为自增类型,或确保每条记录的主键唯一
public class CallHistory { [PrimaryKey, AutoIncrement] // 开启自增避免主键冲突 public int Id { get; set; } public string PhoneNumber { get; set; } public int CallDuration { get; set; } public DateTime CallTime { get; set; } }
4. 开启SQLite日志排查执行语句
通过日志查看实际执行的SQL语句,确认每次插入的参数是否正确:
SQLiteConnection.SetConfiguration(new SQLiteConfig { Log = (message) => Console.WriteLine(message) });
日志会输出每条INSERT语句的参数值,可直接定位是否存在参数覆盖或重复的问题。
内容的提问来源于stack exchange,提问作者Matthew Pans
相关产品推荐
相关产品推荐

