【问题标题】:How can I create a LINQ statement where the table name (FROM) and column name (SELECT) is variable?如何创建表名 (FROM) 和列名 (SELECT) 可变的 LINQ 语句?
【发布时间】:2012-05-11 12:24:05
【问题描述】:

在我的编程任务中,我走上了一条黑暗的小巷,但愿没有,但现在没有回头路了。

我正在构建一个 SQL 语句,其中表名、列名和 id 值是从查询字符串参数中检索的,即("SELECT [{0}] FROM [{1}] WHERE [Id] = {2};", c, t, id)

但它并不像看起来那么糟糕,我受到保护:

  • 只有经过身份验证的用户(即登录用户)才能执行Page_Load
  • 我正在检查表和列是否都存在 (使用GetSchema 等)
  • 我正在预先检查 Id 是否为整数
  • 我所有的表都有 Id 列
  • 数据库连接相当安全

字段值应为 NVARCHAR(4000) 或 NVARCHAR(MAX) 类型,因此我避免使用 ExecuteScalar,我正在尝试 LINQ ExecuteQuery,因为我喜欢 LINQ。但是我又有点不适应了。

我已经走到这一步了:

    Dim db As New MyDataContext

    Dim result = db.ExecuteQuery(Of ITable)("SELECT [{0}] FROM [{1}] WHERE [Id] = {2};", c, t, id)
  • 这是正确的方法吗?
  • 如何获取第一行和第一列的值?
  • 有更好的选择吗?

附:这是一个 SQL Server 2005 数据库

任何帮助表示赞赏。 谢谢。

【问题讨论】:

  • 如果表名或列​​名包含括号,则检查通过(存在),但导致SQL无效。使用quotename。总是。
  • 你说的是方括号还是花括号?
  • 是的,它是有效的 SQL。现在假设该表名为Web]Page。 100% 允许。
  • 是的,只要表 Web]Page 存在,它将起作用。也可以是WebPage[1]。或者类似的东西。关键是,你正在做的那种替代并不能保护你免受任何伤害。始终使用quotename 作为对象名称(首先收集输入,然后为每个项目调用quotename,然后将经过清理的字符串替换为查询)。即使对于您当前的数据架构而言,这看起来有点过头了,但它会确保您将来不会遇到问题。
  • 我会改用 oData 或 .Net Web API 之类的东西。

标签: asp.net sql-server vb.net linq-to-sql webforms


【解决方案1】:

SQL Server 要求表和列是静态已知的。您不能使用命令参数提供它们。你不能说

select * from @tableName

因为表名不能是变量。

您需要使用 C# 构建 SQL 字符串,以确保正确转义标识符。转义是这样的:

var escaped = "[" + rawUntrustedUserInput.Replace("]", "]]") + "]";

这是安全的。

【讨论】:

  • 什么是 rawUntrustedUserInput? “]”呢?
  • "]" 是转义字符。 SELECT QUOTENAME(']') 产生'[]]]'。不需要转义开头的分支(这是我的代码中的一个错误)。
  • 是的,我只是String.Format("[{0}]", tableName.Replace("]", "]]")) 你确定第一个方括号不需要转义吗?你是说 SELECT * FROM [My[Table] 是有效的 T-SQL?
  • 是的,试试吧。如果正确转义,任何字符串都可以成为标识符。就像任何字符串都可以是 C# 字符串文字,如果转义。这两种语言的规则允许这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-17
  • 1970-01-01
相关资源
最近更新 更多