【问题标题】:C# query with dynamic tablename具有动态表名的 C# 查询
【发布时间】:2017-10-16 07:52:35
【问题描述】:

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

代码

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 我该怎么做?
  • 在第二个查询中,您所做的是查询一个字符串,而不是表本身。显然,这不会产生你想要的结果。如果您编写自己的 sql 语句,请注意您无法在 sql 中参数化标识符,因此您必须在 c# 代码中创建查询文本(将 sql 注入的风险降至最低,因为您不涉及用户输入),或者创建一个在内部使用动态 sql 的存储过程(您有更好的机会保护自己免受 sql 注入攻击)。

标签: c# sql linq


【解决方案1】:

表名不能作为参数提供,因此您必须先在函数或存储过程中手动构造 SQL 字符串,然后才能执行它。

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

  exec(@SQLSelectQuery)
END

然后你可以调用proc来以表名作为参数

【讨论】:

  • 你能提供整个查询吗?我操作中的第二个
  • 要非常小心:如果@TableName 来自用户输入,则不会对其进行清理。尽管您使用的是变量,但您正在使用它在 @SQLSelectQuery unsanitized 中生成一个新查询。
【解决方案2】:

要将表名动态输入到第二个查询中,您可以使用存储过程而不是 LINQ。

当你得到你的存储过程,然后你通过传递tablename(你的第一个查询的结果。

SP 文档:https://docs.microsoft.com/en-us/sql/relational-databases/stored-procedures/create-a-stored-procedure

这是一个粗略的例子,只是为了给你一个想法:

  CREATE PROCEDURE InsertProc
   @tablename varchar(100)
  AS
  begin 
   select * from @tablename  
 end 

【讨论】:

  • 我不想用 SP 做。用代码可以做到吗?
  • 嗯..我不知道有什么其他方法,对不起
  • context.Database.ExecuteSqlCommand( " select * from " + tablename); - 不要忘记 SQL 注入
  • 你不能在sql中参数化标识符。
【解决方案3】:
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
}

【讨论】:

  • 此代码无效!您不能将表名作为参数传递。
  • 在这种情况下将表名作为参数传递会抛出 InvalidOperationException
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-25
  • 2016-08-03
  • 2020-03-03
  • 2012-10-28
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多