ASP.NET Core Web API能否实现无固定实体的动态SQL查询?
基于ASP.NET Core Web API实现动态SQL查询结果返回方案
完全可以实现这类需求,针对动态变化的查询结果集,以下是几种实用的实现方案:
方案1:使用ExpandoObject动态构建返回对象
通过ExpandoObject动态生成属性,匹配查询结果的列名和值,最终序列化为JSON返回给前端:
using System.Dynamic; using Microsoft.Data.SqlClient; public async Task<IEnumerable<dynamic>> GetDynamicQueryResult(string sql, SqlParameter[] parameters) { var resultList = new List<dynamic>(); using var connection = new SqlConnection("你的数据库连接字符串"); await connection.OpenAsync(); using var command = new SqlCommand(sql, connection); command.Parameters.AddRange(parameters); using var reader = await command.ExecuteReaderAsync(); while (await reader.ReadAsync()) { dynamic item = new ExpandoObject(); var propertyDict = (IDictionary<string, object>)item; for (int i = 0; i < reader.FieldCount; i++) { var columnName = reader.GetName(i); var columnValue = reader.IsDBNull(i) ? null : reader.GetValue(i); propertyDict[columnName] = columnValue; } resultList.Add(item); } return resultList; }
返回的JSON会自动包含所有查询列,前端可直接解析动态结构。
方案2:用DataTable承载结果集
将查询结果填充到DataTable,ASP.NET Core会自动将其序列化为包含列元数据的JSON:
using System.Data; using Microsoft.Data.SqlClient; public async Task<DataTable> GetQueryResultAsDataTable(string sql, SqlParameter[] parameters) { var dataTable = new DataTable(); using var connection = new SqlConnection("你的数据库连接字符串"); await connection.OpenAsync(); using var command = new SqlCommand(sql, connection); command.Parameters.AddRange(parameters); using var adapter = new SqlDataAdapter(command); adapter.Fill(dataTable); return dataTable; }
这种方式适合需要保留列类型、长度等元数据的场景,前端可通过Columns信息做更细致的渲染处理。
方案3:手动构建JObject(基于Newtonsoft.Json)
使用JObject逐个构建返回对象,可精细控制序列化逻辑:
using Newtonsoft.Json.Linq; using Microsoft.Data.SqlClient; public async Task<IEnumerable<JObject>> GetQueryResultAsJObjects(string sql, SqlParameter[] parameters) { var resultList = new List<JObject>(); using var connection = new SqlConnection("你的数据库连接字符串"); await connection.OpenAsync(); using var command = new SqlCommand(sql, connection); command.Parameters.AddRange(parameters); using var reader = await command.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var jObj = new JObject(); for (int i = 0; i < reader.FieldCount; i++) { var columnName = reader.GetName(i); var columnValue = reader.IsDBNull(i) ? null : reader.GetValue(i); jObj[columnName] = JToken.FromObject(columnValue); } resultList.Add(jObj); } return resultList; }
关键注意事项
- 必须防范SQL注入:所有用户输入的查询片段、参数都要通过
SqlParameter传入,绝对禁止直接拼接SQL字符串。 - 若使用EF Core,可结合
FromSqlRaw或EF Core 7+的SqlQuery执行动态查询,但直接使用ADO.NET灵活性更高。 - 前端需适配动态JSON结构,比如通过遍历键值对渲染表格或表单组件。
内容的提问来源于stack exchange,提问作者joaopedrooo
相关产品推荐
相关产品推荐

