在EntityFrameworkCore 2中使用.FromSql执行存储过程的实现问题
在EF Core 2.x中调用SQL Server存储过程的完整实现
我来帮你补全这个方法,并且把关键细节说清楚——EF Core 2.x调用返回实体列表的存储过程其实很直接,主要用FromSql方法就可以搞定:
完整的方法代码
public IList<Trader> GetTradersWithinRadius(int category, decimal latitude, decimal longitude) { var sproc = "FindTradersWithinRadius"; var sqlParams = new List<SqlParameter>() { new SqlParameter("@CATEGORY", category), new SqlParameter("@LATITUDE", latitude), new SqlParameter("@LONGITUDE", longitude), }; // 调用存储过程并映射到Trader实体列表 return this.Traders .FromSql($"{sproc} @CATEGORY, @LATITUDE, @LONGITUDE", sqlParams.ToArray()) .ToList(); }
关键细节说明
FromSql的作用:这个方法允许你直接执行原生SQL(包括存储过程),并将结果映射到DbSet<T>对应的实体类型。这里我们传入存储过程名称和预先定义的SqlParameter数组,既保证了可读性,又避免了SQL注入风险。- 参数传递:你手动创建
SqlParameter的方式非常安全,EF Core会自动处理参数绑定,不需要你手动拼接SQL字符串。 - 实体映射要求:
- 你的
Trader实体必须在DbContext中注册为DbSet<Trader>(也就是this.Traders)。 - 存储过程返回的结果集列名必须和
Trader实体的属性名匹配(SQL Server默认大小写不敏感,但最好保持一致)。如果列名和属性名不匹配,可以在实体属性上添加[Column("存储过程列名")]特性来做映射。
- 你的
可选的简化写法
如果你不想手动创建SqlParameter,也可以用占位符的方式让EF Core自动帮你生成参数,代码会更简洁:
public IList<Trader> GetTradersWithinRadius(int category, decimal latitude, decimal longitude) { return this.Traders .FromSql("EXEC FindTradersWithinRadius @CATEGORY = {0}, @LATITUDE = {1}, @LONGITUDE = {2}", category, latitude, longitude) .ToList(); }
特殊情况处理
如果你的存储过程返回的不是完整的Trader实体字段,而是自定义的结果集,那么你需要创建一个DTO类,然后用context.Query<CustomDto>().FromSql(...)来映射——不过要记得先安装Microsoft.EntityFrameworkCore.Relational包,Query<T>方法在这个包里。
内容的提问来源于stack exchange,提问作者Matthew Flynn
相关产品推荐
相关产品推荐

