参数不起作用
本文关键字:不起作用 参数 | 更新日期: 2023-09-27 18:32:00
我正在尝试通过以下简单查询使用 Dapper orm:
var sqlString = new StringBuilder();
sqlString.Append("select a.acct AccountNumber,");
sqlString.Append(" b.first_name FirstName,");
sqlString.Append(" b.last_name LastName,");
sqlString.Append(" a.rr RrNumber,");
sqlString.Append(" c.addr1 AddressLine1,");
sqlString.Append(" c.addr2 AddressLine2,");
sqlString.Append(" c.addr3 AddressLine3,");
sqlString.Append(" c.addr4 AddressLine4,");
sqlString.Append(" c.addr5 AddressLine5,");
sqlString.Append(" c.addr6 AddressLine6,");
sqlString.Append(" c.addr7 AddressLine7,");
sqlString.Append(" c.addr8 AddressLine8 ");
sqlString.Append("from (pub.mfclac as a left join pub.mfcl as b on a.client=b.client) ");
sqlString.Append("left join pub.mfclad as c on a.client=c.client ");
sqlString.Append("where a.acct = '@ZYX'");
var connection = new OdbcConnection(_connectionString);
var result = connection.Query(sqlString.ToString(),
new
{
ZYX = accountNumber
});
但是,当我使用已知存在的帐号执行此操作时,dapper 不返回任何内容。所以我试图删除引号以验证参数实际上被替换为帐号,但是从服务器返回的错误表明"@ZYX"周围的语法错误。 这意味着 dapper 不会用给定的值替换参数。 知道为什么会这样吗? 从那里有限的文档中,这应该"正常工作"。
编辑1
无法让这个工作。 使用 string.format 插入参数作为解决方法。
这里有两个问题; 首先(尽管您在问题中注意到了这一点) where a.acct = '@ZYX'
,在 SQL 规则下,不使用任何参数 - 它看起来匹配恰好包含@
符号的文字字符串。对于 SQL-Server(请参阅下面的注释),正确的用法是 where a.acct = @ZYX
。
然而!由于您使用的是OdbcConnection
,命名参数不适用。如果您实际上要连接到类似 SQL-Server 的东西,我强烈建议使用纯 ADO.NET 客户端,它具有比 ODBC 更好的功能和性能。但是,如果 ODBC 是您的唯一选择:它不使用命名参数。直到几天前,这还代表一个主要问题,但根据使用 OleDB 在 Dapper 中传递查询参数,代码(但尚未包含 NuGet 包)现在支持 ODBC。如果从源代码构建(或等待下一个版本),您应该能够使用:
...
where a.acct = ?
在您的命令中,并且:
var result = connection.Query(sqlString.ToString(),
new {
anythingYouLike = accountNumber
});
请注意,ODBC 不使用名称 (anythingYouLike
),因此可以...任何你喜欢的东西。在更复杂的场景中,例如:
.Execute(sql, new { id = 123, name = "abc", when = DateTime.Now });
dapper 使用一些关于匿名类型如何实现的知识来理解值的原始顺序,以便它们以正确的顺序添加到命令中(id
、name
、when
)。
最后一点意见:
这意味着 dapper 不会用给定的值替换参数。
Dapper 从不将参数替换为给定值。这根本不是参数化 sql 的正确方法:参数通常单独发送,确保:
- 没有SQL注入风险
- 最大查询计划重用数
- 没有格式问题
请注意,一些 ADO.NET/ODBC提供商理论上可以选择通过替换在内部实现 - 但这与dapper是分开的。
我从dublicate问题降落在这里:Dapper必须声明标量变量
错误:必须声明标量变量"@Name"。
我用这段代码动态创建了查询:
public static bool Insert<T>(T entity)
{
var tableName = entity.GetType().CustomAttributes.FirstOrDefault(x => x.AttributeType.Name == nameof(TableAttribute))?.ConstructorArguments?.FirstOrDefault().Value as string;
if (string.IsNullOrEmpty(tableName))
throw new Exception($"Cannot save {entity.GetType().Name}. Database models should have [Table('"tablename'")] attribute.");
DBSchema.TryGetValue(tableName.ToLower(), out var fields);
using (var con = new SqlConnection(ConnectionString))
{
con.Open();
var sql = $"INSERT INTO [{tableName}] (";
foreach (var field in fields.Where(x => x != "id"))
{
sql += $"[{field}]"+",";
}
sql = sql.TrimEnd(',');
sql += ")";
sql += " VALUES (";
foreach (var field in fields.Where(x => x != "id"))
{
sql += "@"+field + ",";
}
sql = sql.TrimEnd(',');
sql += ")";
var affectedRows = con.Execute(sql, entity);
return affectedRows > 0;
}
}
当我的模型是这样的时,我得到了同样的错误:
[Table("Users")]
public class User
{
public string Name;
public string Age;
}
我把它们改成这样:
[Table("Users")]
public class User
{
public string Name { get; set; }
public string Age { get; set; }
}
它为我解决了问题。