gpt4 book ai didi

c# - 在 C# 中使用 SQLite 的 Dapper 查询抛出错误 "' 必须为以下参数添加值”

转载 作者:行者123 更新时间:2023-12-05 03:40:18 26 4
gpt4 key购买 nike

我正在尝试对 SQLite 3 数据库执行以下 Dapper 查询:

conn.QuerySingleOrDefault<DalTableConfig>
("select id, modelId, tableName, schemaName
from tables where tableName = $tableName;", new {tableName});

执行这一行,我得到这个错误:

System.InvalidOperationException: 'Must add values for the following parameters: $tableName'

Google 给出了很多结果,一个常见的结果是参数区分大小写,但这在此处不适用,大小写确实匹配。

StackOverflow 有一个 other question有一个未被接受但有效的答案,这是一种解决方法,如下所示:

var parameters = new DynamicParameters();
parameters.Add("@tableName" , tableName);
conn.QuerySingleOrDefault<DalTableConfig>("select id, modelId, tableName, schemaName from tables where tableName = $tableName;", parameters);

这没有我之前得到的异常,但我仍然想知道为什么更简单的匿名对象参数不起作用。

我调试了 Dapper 源代码并发现了问题出现的地方。 SqlMapper 类的 QuerySingleOrDefault 方法的第二行抛出异常:

var command = new CommandDefinition(sql, param, transaction, commandTimeout, commandType, CommandFlags.None);
return QueryRowImpl<T>(cnn, Row.SingleOrDefault, ref command, typeof(T));

此处 param 包含正确的 tableName 属性,command 在其 Parameters 集合中包含此属性。当我检查 QueryRowImpl 方法时,我发现了这段代码:

private static T QueryRowImpl<T>(IDbConnection cnn, Row row, ref CommandDefinition command, Type effectiveType)
{
object param = command.Parameters;
var identity = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param?.GetType());
var info = GetCacheInfo(identity, param, command.AddToCache);

IDbCommand cmd = null;
IDataReader reader = null;

bool wasClosed = cnn.State == ConnectionState.Closed;
try
{
cmd = command.SetupCommand(cnn, info.ParamReader);

if (wasClosed) cnn.Open();
reader = ExecuteReaderWithFlagsFallback(cmd, wasClosed, (row & Row.Single) != 0
? CommandBehavior.SequentialAccess | CommandBehavior.SingleResult // need to allow multiple rows, to check fail condition
: CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow);

这在下面一行失败了。就是这个方法抛出了异常:

ExecuteReaderWithFlagsFallback

在上面的代码中,CommandDefinition command参数仍然有一个有效的Parameters集合,但是局部变量IDbCommand cmd来自SetupCommand 奇怪的是,有两个空的 Parameters 集合。所以似乎 SetupCommandinfo.ParamReader 有一些错误导致参数丢失

最佳答案

我能够在测试中重现这个问题。下面的测试表明,当在 SQL 中使用 @tableName 而不是 $tableName 时,OP 的原始代码有效。

public class DalTableConfig
{
public int Id { get; set; }
public string ModelId { get; set; }
public string TableName { get; set; }
public string SchemaName { get; set; }
}

public class DapperTests
{
[Fact]
public void StackOverflowDapperTest()
{
using var conn = new SqliteConnection("Data Source=test.db");

conn.Execute("drop table if exists tables");
conn.Execute("create table tables(id int, modelId varchar(255), tableName varchar(255), schemaName varchar(255))");
conn.Execute("insert into tables select 1, 'modelId1', 'tableName1', 'schemaName1'");

const string sql = @"
select
id
,modelId
,tableName
,schemaName
from
tables
where
tableName = @tableName"; // here's the fix

const string tableName = "tableName1";

var actual = conn.QuerySingleOrDefault<DalTableConfig>(sql, new {tableName});

Assert.NotNull(actual);
Assert.Equal(tableName, actual.TableName);
}
}

关于c# - 在 C# 中使用 SQLite 的 Dapper 查询抛出错误 "' 必须为以下参数添加值”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68185430/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com