SQL查询在Navicat可正常运行但VB.NET中无法获取返回数据问题
问题原因
- 实体映射规则校验失败:使用
Database.SqlQuery(Of T)执行原生SQL查询时,EF会按照传入的泛型类型的属性映射规则匹配查询返回的列。你的ebook实体中id_ebook被标记为非空主键,但你写的查询SQL只返回了nama_penerbit单个字段,主键等其余字段值全为null,EF反序列化实体时会直接抛出映射错误。 - 空异常捕获吞掉了报错信息:你的仓储方法里
Catch块没有任何日志记录、错误抛出逻辑,异常触发后直接跳过赋值步骤,返回初始化的空集合,导致接口拿不到数据,也看不到具体报错。 - 额外注意:你在Navicat中测试的SQL是
ORDER BY版本,仓储里实际执行的是GROUP BY版本,两个语句不一致,后续调试要保证执行的SQL完全相同。
解决方案
方案1:使用专用DTO接收结果(推荐)
不要用完整的ebook实体接收单字段查询结果,新建一个仅包含所需字段的传输类:
Public Class PenerbitItem Public Property nama_penerbit As String End Class
修改仓储层代码,补全异常处理逻辑,禁止空Catch:
Public Function PenerbitEbookRepository() As List(Of PenerbitItem) ' 去重查出版社直接用DISTINCT即可,不需要GROUP BY Dim sql = "SELECT DISTINCT nama_penerbit FROM Digitalbook.digitalbook.ebook WHERE nama_penerbit IS NOT NULL ORDER BY nama_penerbit" Dim result As New List(Of PenerbitItem) Try result = db.Database.SqlQuery(Of PenerbitItem)(sql).ToList() Catch ex As Exception ' 实际项目中这里可以写日志,不要直接吞异常 Throw End Try Return result End Function
同步修改控制器的返回类型:
<Route("api/Ebooks/GetAllPenerbit")> <HttpGet> Function GetAllPenerbit() As JsonResult(Of List(Of PenerbitItem)) Dim repo As New EbookReposity Return Json(repo.PenerbitEbookRepository()) End Function
方案2:直接用EF LINQ实现查询(最简洁)
这种简单的去重查询不需要写原生SQL,用LINQ可以完全避免字段映射问题:
Public Function PenerbitEbookRepository() As List(Of String) Try Return db.ebook. Where(Function(e) Not String.IsNullOrEmpty(e.nama_penerbit)). Select(Function(e) e.nama_penerbit). Distinct(). OrderBy(Function(name) name). ToList() Catch ex As Exception Throw End Try End Function
控制器对应将返回类型改为JsonResult(Of List(Of String))即可,不需要额外定义DTO。
不推荐修改SQL补全
ebook实体所有字段的方案:你的需求是获取去重后的出版社名称,查全量字段会返回大量冗余数据,性能差,而且如果后续实体字段变动还要同步修改SQL,维护成本高。
内容的提问来源于stack exchange,提问作者Dwi Reza
相关产品推荐
相关产品推荐

