You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Entity Framework Core改写.NET Core 3.1 WebAPI的SQL查询?

解决EF Core LINQ连接查询的作用域错误问题

嘿,我看出来你这儿卡壳的地方了——之前用原生SQL因为邮箱带特殊字符触发MySQL报错,转用EF的LINQ查询又碰到了连接的作用域问题,确实挺让人头疼的。

先看你写的这段出问题的代码:

var query = ( from u in _dbContext.User 
              join userRoles in _dbContext.UsersRoles on u.id equals userRoles.UserId 
              join r in _dbContext.Role on r.id equals userRoles.RoleId 
              where u.email == username 
              select u);

错误提示“名称'r'在'equals'左侧的作用域中不存在”,原因其实很直白:在LINQ的join语法规则里,equals左边必须是前面已经被引入到查询中的集合成员,你这里把r.id放在左边,但r是你当前这个join才要引入的集合,编译器这会儿还不知道r是什么,自然就报错了。

正确的写法应该把userRoles.RoleId放在equals左边,r.Id放在右边——毕竟userRoles是上一个join已经定义好的,编译器能识别它:

// 修正后的查询
var query = from u in _dbContext.User
            join userRoles in _dbContext.UsersRoles on u.id equals userRoles.UserId
            join r in _dbContext.Role on userRoles.RoleId equals r.Id // 调换equals左右的顺序
            where u.email == username
            select new 
            {
                id = u.Id,
                email = u.Email,
                name = u.name,
                lastname = u.lastname,
                phoneNumber = u.PhoneNumber,
                role = r.name
            };

// 获取结果,和你之前的SingleOrDefault逻辑一致
var user = query.SingleOrDefault();

另外还有两个小细节要注意:

  • 你原来的原生SQL是要查询包含角色名的组合数据,所以别直接select u,得像上面那样构造匿名对象(或者你可以专门建一个DTO类来接收这些字段),这样才能拿到和原SQL一致的返回结果。
  • 用这种LINQ写法不仅解决了特殊字符导致的MySQL报错,还能彻底避免SQL注入风险——EF会自动帮你处理参数化查询,比用String.Format拼SQL安全太多了。

内容的提问来源于stack exchange,提问作者yodellingbutters

火山引擎 最新活动