【发布时间】:2021-03-26 23:29:05
【问题描述】:
该应用是 .Net Core 3.1,使用 EF Core 3 和 Azure 上的 SQL Server
所以我试图在我的数据库中使用来自客户端的数据创建一个表,并且我希望避免 SQL 注入。
到目前为止,我已经尝试使用 FormattableString,根据doc,它可以安全地防止 SQL 注入:
public Task CreateTableAsync(string tableName, JSchema tableSchema)
{
return TransactionAsync(async () =>
{
// Get the fields for the table creation
var fields = await ParseJSchemaForCreationAsync(tableSchema);
var sql = "CREATE TABLE {0} (";
var sqlParams = new List<object>
{
tableName
};
var first = true;
var count = 1;
foreach (var entry in fields)
{
// entry.Value is from code so it's safe againt injection
sql += first ? $"{{{count}}} {entry.Value}" : $", {{{count}}} {entry.Value}";
first = false;
sqlParams.Add(entry.Key);
count++;
}
sql += ");";
var safe = FormattableStringFactory.Create(sql, sqlParams.ToArray());
// Create the table
await _dbContext.Database.ExecuteSqlInterpolatedAsync(safe);
});
}
但我有一个错误:“'@p0' 附近的语法不正确”,尽管它似乎生成了一个有效的查询(当我得到 sage 的值时: “创建表 sqlDataSourceGrainTest (Id uniqueidentifier NOT NULL PRIMARY KEY, CreatedAt datetime2(0), UpdatedAt datetimeoffset(3), FirstName nvarchar(4000), Birthdate date, XId uniqueidentifier, Datetime datetime2(0), Timestamp timestamp, Height decimal(18, 2), HasFoodAllergy bit, Age bigint);"
我也尝试过使用 SQLParameter(我更喜欢):
public Task CreateTableAsync(string tableName, JSchema tableSchema)
{
return TransactionAsync(async () =>
{
// Get the fields for the table creation
var fields = await ParseJSchemaForCreationAsync(tableSchema);
var sql = "CREATE TABLE @tableName (";
var sqlParams = new List<SqlParameter>()
{
new SqlParameter
{
ParameterName = "tableName",
Value = tableName,
}
};
var first = true;
foreach (var entry in fields)
{
sql += first ? $"@{entry.Key} {entry.Value}" : $", @{entry.Key} {entry.Value}";
first = false;
var sqlParam = new SqlParameter
{
ParameterName = $"{entry.Key}",
Value = entry.Key
};
sqlParams.Add(sqlParam);
}
sql += ");";
// Create the table
await _dbContext.Database.ExecuteSqlRawAsync(sql, sqlParams);
});
}
但我遇到了错误:“'@tableName' 附近的语法不正确。”
有人可以帮我找到创建表格的正确方法吗?有没有规定不能用带参数的sql建表。
我还需要更新表格、插入记录和更新记录
谢谢
编辑:基于我尝试过的 DavidG 和 HoneyBadger 的回答:
public Task CreateTableAsync(string tableName, JSchema tableSchema)
{
return TransactionAsync(async () =>
{
// Get the fields for the table creation
var fields = await ParseJSchemaForCreationAsync(tableSchema);
var sql = $"CREATE TABLE {tableName} (";
var sqlParams = new List<SqlParameter>();
var first = true;
foreach (var entry in fields)
{
sql += first ? $"@{entry.Key} {entry.Value}" : $", @{entry.Key} {entry.Value}";
first = false;
var sqlParam = new SqlParameter
{
ParameterName = $"{entry.Key}",
Value = entry.Key
};
sqlParams.Add(sqlParam);
}
sql += ");";
// Create the table
await _dbContext.Database.ExecuteSqlRawAsync(sql, sqlParams);
});
}
但现在错误是“'@id' 附近的语法不正确”,这是第一个参数的名称
SQL 我看到:CREATE TABLE tableTests (@Id uniqueidentifier NOT NULL PRIMARY KEY, @CreatedAt datetime2(0), @UpdatedAt datetimeoffset(3), @FirstName nvarchar(4000), @Birthdate date, @XId uniqueidentifier, @Datetime datetime2(0), @Timestamp 时间戳, @Height decimal(18, 2), @HasFoodAllergy bit, @Age bigint);"
在创建表时我不能使用任何参数吗?
【问题讨论】:
-
SQL Server 不允许您为表名使用参数。
-
您确定您发布的编辑错误准确吗?
-
调试时
tableName的值是多少?似乎您的tableName-参数是"@tableName"- 或者这是一个“旧”错误。如果您通过@tableName,它将不起作用。您不能使用任何 sql 参数作为 tableName。您需要传递实际的表名(不带sql参数) -
抱歉,错过了我的编辑,现在的错误是“'@id 附近的语法不正确”。我在问题中添加了 SQL
标签: c# sql entity-framework-core