为什么这个 ADO.NET 查询 return 没有结果?

Why does this ADO.NET query return no results?

我有以下代码执行 SQL 语句并查找结果。

var sql = @"select BOQ_IMPORT_ID "
          + "from ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
          + "where PROJECT_ID = :Projectid "
          + "order by CREATED_ON desc "
          + "fetch first 1 row only";
using (var conn = new OracleConnection(ApplicationSettings.ConnectionString))
using (var cmd = new OracleCommand(sql, conn))
{
    conn.Open();
    cmd.Parameters.Add(LocalCreateParameterRaw("ProjectId", projectId));
    var reader = cmd.ExecuteReader();
    if (reader.Read())
    {
        byte[] buffer = new byte[16];
        reader.GetBytes(0, 0, buffer, 0, 16);
        var boqId = new Guid(buffer);
        return boqId;
    }

    return null;
}

其中 LocalCreateParameterRaw 声明为:

public static OracleParameter LocalCreateParameterRaw(string name, object value)
{
    OracleParameter oracleParameter = new OracleParameter();
    oracleParameter.ParameterName = name;
    oracleParameter.OracleDbType = OracleDbType.Raw;
    oracleParameter.Size = 16;
    oracleParameter.Value = value;
    return oracleParameter;
}

'projectId' 的基础类型是 'Guid'。

if (reader.Read()) 的计算结果总是 false,尽管 table 中只有一行。它通常应该 return 只有一行。

使用 GI Oracle Profiler 我可以捕获发送到数据库的 SQL,但是探查器只为 :ProjectId 参数提供了一次值,而且是小写的。就这样 return 没有结果,但是一旦我将 UPPER 应用到那个值,我就得到了结果。

看起来我必须以某种方式将我的参数设置为大写才能使查询正常工作,但我不知道如何操作。然而,如果我在 projectId GUID 上执行 ToString().ToUpper(),我会收到参数绑定错误。

非常重要: 我试过完全删除 where 子句,不再添加参数,因此 table 中的所有行都应该 returned,但仍然没有结果。

使用更通用的方法,尝试以下方法

var sql = "SELECT BOQ_IMPORT_ID "
      + "FROM ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
      + "WHERE PROJECT_ID = :projectid "
      + "ORDER BY CREATED_ON DESC "
      + "FETCH FIRST ROW ONLY";
using (DbConnection conn = new OracleConnection(ApplicationSettings.ConnectionString))
using (DbCommand cmd = conn.CreateCommand()) {
    DbParameter parameter = cmd.CreateParameter();
    parameter.ParameterName = "projectid";
    parameter.Value = projectId.ToString("N").ToUpper(); //<-- NOTE FORMAT USED

    cmd.Parameters.Add(parameter);
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = sql;

    conn.Open();

    var reader = cmd.ExecuteReader();
    if (reader.Read()) {
        var boqId = new Guid((byte[])reader[0]);
        return boqId;
    }
    return null;
}

It looks like I somehow have to get my parameter into uppercase for the query to work, but I have no idea how. Yet if I do a ToString().ToUpper() on the projectId GUID, I get a parameter binding error.

引用Guid.ToString Method

Specifier N formats it to 32 digits: 00000000000000000000000000000000

如果未提供格式,则默认格式为 D,其中包含 32 位数字,用连字符分隔。

00000000-0000-0000-0000-000000000000

这可以解释您的绑定错误。

我不知道怎么做,但是将 SQL 字符串设为逐字字符串(以 @ 为前缀)会导致 proc 工作。所以,它不适用于:

var sql = @"SELECT BOQ_IMPORT_ID "
      + "FROM ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER "
      + "WHERE PROJECT_ID = :projectid "
      + "ORDER BY CREATED_ON DESC "
      + "FETCH FIRST ROW ONLY";

然而 SQL Developer 中的相同命令字符串执行并 returns 结果。当我逐字逐句制作 SQL 字符串时,如下所示,我得到了结果。

var sql = @"select BOQ_IMPORT_ID 
            from ITIS_PRJ.PRJ_BOQ_IMPORT_HEADER 
            where PROJECT_ID = :ProjectId 
            order by CREATED_ON desc 
            fetch first 1 row only";