0

我想知道是否可以将表前缀保留在配置文件中并SqlCommand通过将其附加到实际表名来在每个查询中使用它,因此具有相同表结构的两个应用程序可以使用相同的数据库而不共享数据。

截至目前,我所有的SqlCommand查询都是这样的:

using (var connection = new SqlConnection(connString))
{
    using (SqlCommand sqlCmd = new SqlCommand("SELECT * from SomeTable", connection))
    {
        connection.Open();

        using (SqlDataReader dr = sqlCmd.ExecuteReader())
        {
            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    Model _record = new Model();
                    _record.ID = Convert.ToInt32(dr["ID"]);
                    _record.Value = Convert.ToString(dr["Value"]);

                    RecordsList.Add(_record);
                }
            }
        }

        connection.Close();

        return RecordsList;
    }
}

或者:

using (var connection = new SqlConnection(connString))
{
    using (SqlCommand sqlCmd = new SqlCommand("UPDATE SomeTable SET Value = @Value " +
                                              "WHERE ID = @Id;", connection))
    {
        sqlCmd.Parameters.Add("@Value", System.Data.SqlDbType.NVarChar).Value = _record.Value;
        sqlCmd.Parameters.Add("@Id", System.Data.SqlDbType.Int).Value = _record.Id;

        connection.Open();
        sqlCmd.ExecuteNonQuery();
        connection.Close();
    }
}

如您所见,我使用参数,但不能在表名上使用参数。

如果我想添加prefix_到表名的开头,那么保护查询免受 SQL 注入的方法应该是什么,所以应用程序会与存储在设置文件中的带有前缀的表进行对话?

4

2 回答 2

2

这是一个简单的实用函数,用于将表名包装在分隔符中,并防止 SQL 注入。这是 TSQL QUOTENAME函数的 C# 实现:

    private static string QuoteName(string identifier)
    {
        var sb = new StringBuilder(identifier.Length + 3, 1024);
        sb.Append('[');
        foreach (var c in identifier)
        {
            if (c == ']')
                sb.Append(']');
            sb.Append(c);
        }
        sb.Append(']');
        return sb.ToString();
    }

你会像这样使用它:

var sql = $"UPDATE {QuoteName(SomePrefix + "_" + SomeTable)} SET Value = @Value WHERE ID = @Id;"
于 2020-03-14T18:36:49.290 回答
0

简单的答案:有可能吗?是的。这是个好主意吗?在绝大多数情况下不是。

如果您正在考虑这种技巧,那么它表明更好的整体设计策略是合适的。诸如所有者模式和多租户设计之类的概念很常见并且有据可查,它们提供了一种更简洁且受平台支持的数据存储隔离方法。

诸如前缀想法之类的技巧几乎总是会在应用程序的整个生命周期中导致灾难性问题,除非采用精英级别的基础设施设计。即便如此,一些最佳实施的设计也经常存在问题。

于 2020-03-14T17:58:52.140 回答