.NET Core+EF如何从SQL查询返回Person模型字段子集为JSON?
这个错误的根源很明确——你把方法的返回类型声明成了IEnumerable<List>,但实际返回的是List<Person>,这两个类型完全不兼容,而且你还想只返回Person的部分字段,直接返回Person实例显然也不符合需求。下面给你几个靠谱的解决方案,还顺便帮你修复一个隐藏的安全问题:
方案1:用匿名类型快速实现(适合简单场景)
把返回类型改成IActionResult(ASP.NET Core API里推荐用这个,能灵活返回不同状态码),然后用LINQ的Select投影出你需要的字段,这样EF会自动生成只查询这两个字段的SQL,而且不会有SQL注入风险:
[HttpGet("{userGuid}")] public IActionResult GetUserInfo([FromRoute] string userGuid) { var userInfo = _context.Person .Where(p => p.UserGuid == userGuid) .Select(p => new { p.PersonId, p.Name }) .ToList(); return Ok(userInfo); // 自动序列化为只含PersonId和Name的JSON }
这里要重点提醒:你原来的FromSql直接拼接userGuid字符串,这是严重的SQL注入漏洞,绝对不能这么写!用LINQ的Where会让EF自动处理参数化,彻底避免这个风险。
方案2:创建DTO类(适合需要复用或类型明确的场景)
如果这个字段子集需要在多个接口或服务中复用,最好创建一个专门的数据传输对象(DTO),这样类型更清晰,也方便后续维护:
首先定义DTO:
public class PersonInfoDto { public int PersonId { get; set; } public string Name { get; set; } }
然后修改接口方法:
[HttpGet("{userGuid}")] public IEnumerable<PersonInfoDto> GetUserInfo([FromRoute] string userGuid) { return _context.Person .Where(p => p.UserGuid == userGuid) .Select(p => new PersonInfoDto { PersonId = p.PersonId, Name = p.Name }) .ToList(); }
这样返回的JSON同样只会包含你需要的两个字段,而且返回类型明确,调用方也能更清楚知道返回的数据结构。
如果你一定要用FromSql(不推荐,但可以这么做)
如果你因为某些原因必须用原生SQL查询,一定要用参数化查询避免注入,然后再投影到目标类型:
[HttpGet("{userGuid}")] public IActionResult GetUserInfo([FromRoute] string userGuid) { var userInfo = _context.Person .FromSql(@"SELECT p.PersonId, p.Name FROM dbo.person p WHERE p.UserGuid = @userGuid", new SqlParameter("@userGuid", userGuid)) .Select(p => new { p.PersonId, p.Name }) .ToList(); return Ok(userInfo); }
注意:FromSql返回的是Person实例,即使你只查了部分字段,其他字段会是默认值(比如0、null),所以必须用Select投影,否则返回的JSON会包含Person的所有字段(其他字段是默认值),这不是你想要的效果。
最后总结几个核心要点:
- 永远不要直接拼接用户输入到SQL字符串里,避免SQL注入。
- 返回部分字段时,用
Select投影到匿名类型或DTO,不要直接返回完整的实体模型。 - 修正方法的返回类型,确保和实际返回的类型匹配。
内容的提问来源于stack exchange,提问作者blarg
相关产品推荐
相关产品推荐

