Microsoft.Data.Sqlite.SqliteException:“SQLite Error 1: ‘no such column: t.Value‘.”

问题现象

使用EF core获取SQLite的sequence 时一直有此错误:Microsoft.Data.Sqlite.SqliteException:“SQLite Error 1: 'no such column: t.Value'.”

以下是出错代码:

 var id = DbContext.Instance.Database.SqlQuery<int>($"SELECT seq+1 FROM sqlite_sequence WHERE name='deviceInfo'").First();

排查过程

通过不断的尝试后,发现取消First()就是正常的,一旦要使用First()方法就会异常,怀疑IQueryable.First()实现应该是有问题。

询问了下GPT,其给出的原因如下:

按其所述将上述代码改为了如下,多次测试没有问题.

var id = DbContext.Instance.Database.SqlQuery<int>($"SELECT seq+1 FROM sqlite_sequence WHERE name='deviceInfo'").ToList().First();

 另上述代码中,若将

name='deviceInfo'

采用"{}" 插值的方式,也是有问题的,报错如下:

报此错误的代码如下:

 string tableName = "deviceInfo";
 var id = DbContext.Instance.Database.SqlQuery<int>($"SELECT seq+1 FROM sqlite_sequence WHERE name='{tableName}'").ToList().First();

 不得以只能将其写成硬代码。各位若有更好的解决办法,望留言。

原因分析

从查询资料与AI给出的结果来看,大概率是IQueryable<T>的实现应该是有一些问题。 

也就是说其实不是出在 SQL 本身(SELECT seq+1 FROM sqlite_sequence WHERE name='deviceInfo'),而是 EF Core 在处理 SqlQuery<int>() 返回结果时出了问题
原因是 EF Core 8(以及更早版本)中,Database.SqlQuery<T> 在底层会自动生成一些内部 SQL(如 SELECT t.Value FROM (...) AS t),从而在你的自定义查询结果中找不到名为 Value 的列。

SqlQuery<int>() 期望查询结果中 列名为 Value 或与类型映射对应
但你的查询返回的列名是 seq+1(没有别名),所以 EF Core 生成的包装查询访问 t.Value 时找不到对应列,导致报错。

解决办法

1.在排查过种已经有所介绍,即将查询到的IQueryable<T>转化为list,然后再做处理即可。

2.给查询列一个别名为 Value

var id = DbContext.Instance.Database .SqlQuery<int>($"SELECT seq + 1 AS Value FROM sqlite_sequence WHERE name='deviceInfo'") .First();

这样 EFCore 在映射结果时能找到 Value 列并正确转换为 int

3.也可以使用匿名类型或 DTO 包装:

var result = DbContext.Instance.Database .SqlQuery<(int seq)>("SELECT seq + 1 AS seq FROM sqlite_sequence WHERE name='deviceInfo'") .First(); int id = result.seq;

4.如果只是想简单获取某个值,也可以直接用普通 SQL 执行器:

using var cmd = DbContext.Instance.Database.GetDbConnection().CreateCommand(); cmd.CommandText = "SELECT seq + 1 FROM sqlite_sequence WHERE name='deviceInfo'"; DbContext.Instance.Database.OpenConnection(); var result = cmd.ExecuteScalar(); int id = Convert.ToInt32(result);

方式写法是否推荐
1. 使用别名 Value✅ 简洁,推荐✅✅✅
2. 使用元组或 DTO✅ 可读性好✅✅
3. ExecuteScalar低层次但稳定✅(仅在不依赖 EFCore 映射时)

望本文能帮助各位避此大坑……

注意:不要使用插值方式写sql语句,否则会造成sql漏洞,会导致数据库被提权,此一定要注意。推荐进行参数化查询,以避免此问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值