直接执行 SQL 语句查询

使用场景

当 LINQ 查询难以表达,或者生成的 SQL 性能不佳(如产生多次查询、低效的 CASE 嵌套等)时,可以直接在 DataContext 上执行原生 SQL 语句。

代价:​ 失去编译期类型检查,SQL 写错只能在运行时发现;且需要预先定义好接收结果的实体类。


基础用法

using (var db = new DataClasses1DataContext())
{
    // 直接执行 SELECT,结果映射到 StudentInfo 类
    var res = db.ExecuteQuery<StudentInfo>(
        "select Student.ID, Student.Name, Classx.Name as ClassName " +
        "from Student join Classx on Student.ClassID = Classx.ID"
    ).ToList();
}Code language: JavaScript (javascript)

要求:StudentInfo 类的属性名必须与查询结果集的列名匹配(不区分大小写,但建议一致):

public class StudentInfo
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string ClassName { get; set; }
}Code language: JavaScript (javascript)

带参数的查询

方式一:参数化传参(推荐,安全)

var res2 = db.ExecuteQuery<StudentInfo>(
    "select Student.ID, Student.Name, Classx.Name as ClassName " +
    "from Student join Classx on Student.ClassID = Classx.ID AND Student.ID = {0}",
    "2"
).ToList();Code language: JavaScript (javascript)

{0} 是参数占位符,ExecuteQuery 会将其作为参数化查询发送给数据库,等效于:

exec sp_executesql N'select ... AND Student.ID = @p0', N'@p0 nvarchar(1)', @p0=N'2'Code language: JavaScript (javascript)

方式二:字符串拼接(不推荐,有注入风险)

// 直接拼入 SQL 字符串
var res2 = db.ExecuteQuery<StudentInfo>(
    "select Student.ID, Student.Name, Classx.Name as ClassName " +
    "from Student join Classx on Student.ClassID = Classx.ID AND Student.ID = 2"
).ToList();Code language: JavaScript (javascript)

LIKE 查询的注意事项

// 下面这样写可能查不到结果!
var res3 = db.ExecuteQuery<StudentInfo>(
    "select Student.ID, Student.Name, Classx.Name as ClassName " +
    "from Student join Classx on Student.ClassID = Classx.ID " +
    "AND Student.Name like ''%{0}%''",
    "李"
).ToList();Code language: JavaScript (javascript)

问题原因:

ExecuteQuery{0} 占位符会被当作参数传递。当 LIKE '%李%' 作为参数时,数据库收到的是:

exec sp_executesql N'... AND Student.Name like @p0', N'@p0 nvarchar(1)', @p0=N'%李%'Code language: JavaScript (javascript)

在某些数据库配置下(如 varchar vs nvarchar 隐式转换、排序规则不匹配),参数化 LIKE 可能不走索引或匹配失败。

解决方案一:直接在 SQL 中拼接通配符(参数只传纯值)

// 占位符只接收纯值,通配符写在 SQL 里
var res3 = db.ExecuteQuery<StudentInfo>(
    "select Student.ID, Student.Name, Classx.Name as ClassName " +
    "from Student join Classx on Student.ClassID = Classx.ID " +
    "AND Student.Name like '%' + {0} + '%'",
    "李"
).ToList();Code language: JavaScript (javascript)

解决方案二:直接拼接完整 SQL(简单场景,确保输入安全)

var keyword = "李";
var res3 = db.ExecuteQuery<StudentInfo>(
    "select Student.ID, Student.Name, Classx.Name as ClassName " +
    "from Student join Classx on Student.ClassID = Classx.ID " +
    $"AND Student.Name like '%{keyword}%'"
).ToList();Code language: JavaScript (javascript)

注意:​ 方案二仅适用于输入可信场景,生产环境应校验输入或改用方案一的 '%' + {0} + '%' 写法。


三种调用方式汇总

写法SQL 参数化安全性适用场景
ExecuteQuery<T>(sql)依赖 SQL 本身SQL 无参数
ExecuteQuery<T>(sql, param)是,{0} 为参数安全单值/多值条件
ExecuteQuery<T>(sql, param1, param2)是,{0}{1} 为参数安全多个条件

执行非查询 SQL(INSERT / UPDATE / DELETE)

// 执行无返回结果集的 SQL
db.ExecuteCommand(
    "UPDATE Student SET Name = {0} WHERE ID = {1}",
    "新名字", 1
);

// 批量删除
db.ExecuteCommand(
    "DELETE FROM booklabel WHERE bid = {0}",
    12
);Code language: JavaScript (javascript)

ExecuteCommand 返回受影响的行数(int)。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注