C# 的 字符串插值($) 和 逐字字符串(@) 功能
这段代码使用了 C# 的 字符串插值($
) 和 逐字字符串(@
) 功能,并在 SQL 语句中动态拼接变量。下面详细解释它们的用法:
1. $
(字符串插值)
$
是 C# 的 字符串插值 符号,允许在字符串中直接嵌入表达式(用 {}
包裹),例如:
string name = "Alice";
string message = $"Hello, {name}!"; // 输出:Hello, Alice!
在 SQL 语句中,$
用于动态插入变量值,如 {level}
、{GetNextSortOrder(parentId)}
等。
2. @
(逐字字符串)
@
是 C# 的 逐字字符串 符号,它会:
- 忽略转义字符(如
\n
、\t
等) - 允许字符串跨多行(适合 SQL 语句)
- 保留所有空格和换行
例如:
string sql = @"SELECT *FROM UsersWHERE Id = 1";
如果不加 @
,换行符需要用 \n
表示,而加了 @
后可以直接换行。
3. $@
(同时使用)
$@
结合了两种功能:
@
允许 SQL 语句跨多行$
允许在字符串中插入变量
所以:
string strsql = $@"INSERT INTO System (PID, Level, SortOrder, Name, remark, CreatedTime, ModifiedTime)VALUES (...)
";
这样既保持了 SQL 语句的可读性,又能动态插入变量。
4. {(level == 3 ? $"'{editForm.Target.Replace("'", "''")}'" : "NULL")}
解释
这段代码是一个 嵌套的三元运算符 + 字符串插值,用于动态生成 SQL 语句中的 remark
字段值:
level == 3
:检查当前节点是否是第 3 级(可能是菜单项)- 如果是,则:
editForm.remark.Replace("'", "''")
:对remark
字符串进行 SQL 转义(单引号'
替换成''
,防止 SQL 注入)$"'{...}'"
:用单引号包裹(因为 SQL 字符串需要用'
括起来)
- 如果不是(
level != 3
),则直接插入NULL
(SQL 的 NULL 值,不加引号)
- 如果是,则:
示例
假设:
level = 3
editForm.remark= "admin/home"
则生成的 SQL 部分:
remark= 'admin/home'
如果 level = 2
,则:
remark= NULL
5. 完整 SQL 拼接示例
假设:
parentId = 1
level = 3
editForm.NodeName = "Admin Page"
editForm.remark = "admin/home"
生成的 SQL 语句:
INSERT INTO System
(PID, Level, SortOrder, Name, remark, CreatedTime, ModifiedTime)
VALUES (1,3,1, -- 假设 GetNextSortOrder(parentId) 返回 1'Admin Page','admin/home',GETDATE(),GETDATE()
)
6. 安全性注意事项
虽然这种拼接方式方便,但存在 SQL 注入风险(如果 NodeName
、Target
等来自用户输入)。更安全的方式是使用 参数化查询(如 SqlCommand.Parameters
):
using (var cmd = new SqlCommand(@"INSERT INTO System (PID, Level, SortOrder, Name, remark, CreatedTime, ModifiedTime)VALUES (@PID, @Level, @SortOrder, @Name, @remark, GETDATE(), GETDATE())", connection))
{cmd.Parameters.AddWithValue("@PID", parentId ?? (object)DBNull.Value);cmd.Parameters.AddWithValue("@Level", level);cmd.Parameters.AddWithValue("@SortOrder", GetNextSortOrder(parentId));cmd.Parameters.AddWithValue("@Name", editForm.NodeName);cmd.Parameters.AddWithValue("@remark", level == 3 ? editForm.Target : (object)DBNull.Value);cmd.ExecuteNonQuery();
}
这样可以有效防止 SQL 注入攻击。