EF Core 3.1非SQL Server库下ExecuteSqlCommand报错如何执行原生SQL
在EF Core 3.1环境下使用PostgreSQL(Npgsql)等非SQL Server数据库时,尝试通过如下代码执行原生SQL:
public object GetRawSqlResult(string request) { object result = ctx.Database.ExecuteSqlCommand(request); return result; }
调用ExecuteSqlCommand方法时出现CS1061编译错误:
CS1061: “DatabaseFacade”不包含“ExecuteSqlCommand”的定义,且未找到接受第一个参数类型为“DatabaseFacade”的可访问扩展方法“ExecuteSqlCommand”(是否缺少using指令或程序集引用?)
Context类中虽存在Database属性,但无法通过Context.Database直接访问原生SQL查询入口。现有官方文档未说明不依赖特定Context实体类时的原生SQL执行方式。
需求为执行纯SQL命令,不需要映射绑定到实体:当前仅持有类名,需要验证对应表是否存在于数据库中,无对应实体实例,需要可直接对数据库执行SQL命令的实现方案。
异常现象参考:
补充:智能提示列表中不存在“ExecuteSqlCommand...”相关方法选项:
EF Core 3.1 版本对原生SQL执行API做了重构,旧版本的ExecuteSqlCommand方法已被正式移除,该编译错误和使用PostgreSQL等非SQL Server数据库没有关联,是版本API变动导致的。
- 首先确保代码文件引入EF Core核心命名空间:
using Microsoft.EntityFrameworkCore;
- 执行无实体映射的原生非查询SQL,使用
ExecuteSqlRaw方法替代旧的ExecuteSqlCommand即可,该方法直接挂载在DatabaseFacade下,不需要关联任何DbSet实体,返回值为SQL执行影响的行数:
public object GetRawSqlResult(string request) { int affectedCount = ctx.Database.ExecuteSqlRaw(request); return affectedCount; }
- 如果需要执行参数化SQL规避注入风险,推荐使用
ExecuteSqlInterpolated方法,以校验表是否存在的需求为例,实现代码如下:
public bool CheckTableExist(string tableName) { // PostgreSQL查询information_schema判断指定表是否存在 int existCount = ctx.Database.ExecuteSqlInterpolated($@" SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_name = {tableName} "); return existCount > 0; }
排查提示:如果引入命名空间后依然找不到上述方法,检查项目中所有EF Core相关NuGet包(包括Npgsql.EntityFrameworkCore.PostgreSQL)版本是否统一为3.1.x,混装不同大版本的EF Core依赖会导致扩展方法加载失败。
内容的提问来源于stack exchange,提问作者Eric Ouellet

