C#使用动态表名进行查询

3

我希望构建一个查询,其中表名将是动态的,并且我将从另一个查询中获取它。这两个查询位于不同的数据上下文中。

代码

var tablename = (from tab in db.Tabs
                 where tab.id == tabid
                 select tab.name).FirstOrDefault();

var pid = (from p in tablename
           select p.id).FirstOrDefault();

在这种情况下,您必须亲自编写SQL语句。但是,您应该使用 SqlCommand 类和其 Parameters 属性来避免注入攻击。 - Oliver
@Oliver 我该怎么做? - alxem
在第二个查询中,您要查询的是一个字符串,而不是表本身。显然,这将不能产生您想要的结果。如果您编写自己的 SQL 语句,请注意,您无法在 SQL 中参数化标识符,因此您将不得不在 C# 代码中创建查询文本(由于此处没有涉及用户输入,因此有最小化 SQL 注入风险),或者创建使用动态 SQL 的存储过程(在其中更容易从 SQL 注入攻击中保护自己)。 - Zohar Peled
3个回答

3

表名不能作为参数提供,因此在执行之前,您必须手动构建 SQL 字符串,可以在函数或存储过程中完成。

    create PROC read_from_dynamic_table(@TableName NVARCHAR(50))
AS
BEGIN 
DECLARE @SQLSelectQuery NVARCHAR(MAX)=''
SET @SQLSelectQuery = 'SELECT * FROM ' + @TableName

  exec(@SQLSelectQuery)
END

然后,您可以调用带有表名参数的存储过程。

你能提供完整的查询吗?在我的观点中是第二个。 - alxem
非常小心:如果 @TableName 是来自用户输入的,那么它就没有经过净化。尽管您正在使用一个变量,但是您正在使用它未经净化地生成一个新查询在 @SQLSelectQuery 中。 - mdip

0

我不想用SP来做。能否用代码实现? - alxem
嗯...我不知道其他的方法,抱歉。 - grepLines
1
context.Database.ExecuteSqlCommand("select * from " + tablename); - 别忘了 SQL 注入。 - ASpirin
在 SQL 中,您无法将标识符参数化。 - Zohar Peled

-6
using(SqlConnection sqlCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
    SqlCommand com = new SqlCommand();
    SqlDataReader sqlReader;

    com.CommandText = "Select id from @tableName";
    com.CommandType = CommandType.Text;
    com.Parameters.Add(new SqlParameter("@tableName", tableName);

    com.Connection = sqlCon;
    sqlCon.Open();
    sqlReader = com.ExecuteReader();

    var dt = new DataTable();
    dt.Load(sqlReader); //Query output is in dt now
}

5
这段代码无法运行!你不能将表名作为参数传递。 - Serkan Arslan
在这种情况下,将表名作为参数传递会引发InvalidOperationException异常。 - Ashique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接