SQLite .NET,ExecuteScalarAsync<int>,如何知道没有结果? (注意:这是一个提问标题,无需回答)

3

这个SQL语句正在检索一行的ID,但是可能不存在这样的行。当我在GUI工具中执行特定的SQL语句时,它返回“从...返回0行,在0ms中返回”。然而,当我使用ExecuteScalarAsync<int>执行相同的SQL语句时,它返回0,没有出现异常或null。我如何知道是否存在这样的行?理论上,可能有一个ID为0的行。

PS:这是我使用Nuget添加的SQLite-net(https://github.com/praeclarum/sqlite-net)。它的版本是1.4.118。 SQL语句非常简单。我更改了字段名称,但基本上是这样的:

using SQLite;

public Task<int> GetLastID()
{
    return RealDatabase.ExecuteScalarAsync<int>
        ("SELECT max(ID) FROM DATA)");
}

1
也许可以使用ExecuteScalarAsync<int?>吗? - Evk
1
当没有匹配时,它返回了 null,但是当有匹配时,它抛出了一个异常。异常信息为:NotSupportedException: 不知道如何读取 System.Nullable1[System.Int32]`。 - Damn Vegetables
@PanagiotisKanavos 那个异常是对第一个评论的回应,不属于问题本身。我认为问题没有代码也很好理解,而且 OP 明确表明没有涉及到异常。 - C.Evenhuis
@DamnVegetables ADO.NET的ExecuteScalarAsync不是通用的,所以它可以返回null。你正在使用哪个库? - Panagiotis Kanavos
2
@DamnVegetables,你正在使用这个提供者吗? 那么你就没那么幸运了,因为有一个未解决的问题,涉及到ExecuteScalar的可空结果。 - Panagiotis Kanavos
显示剩余12条评论
2个回答

1
我用一个扩展方法解决了这个问题:

using System;
using System.Threading.Tasks;
using SQLite;

namespace MyApp.DB
{
    public class Row<T>
    {
        public T scalar_value { get; set; }
    }

    public class Maybe<T>
    {
        public readonly T Value;
        public Maybe(T v) { Value = v;  }
    }

    public static class SQLiteExtensions
    {
        public async static Task<Maybe<T>> QueryScalarAsync<T>(this SQLite.SQLiteAsyncConnection conn, string sql)
        {
            var res = await conn.QueryAsync<Row<T>>(sql);
            if (res.Count == 0)
            {
                return null;
            }
            else
            {
                return new Maybe<T>(res[0].scalar_value);
            }
        }
    }
}

null 的返回值表示未找到任何行,而任何返回值本身都被包装在 Maybe 类中,以便可以区分空值:

var version = await conn_.QueryScalarAsync<int>("SELECT version AS scalar_value FROM schema_version");
if (version == null)
{
    Debug.WriteLine("no rows found");
}
else
{
    Debug.WriteLine(string.Format("value = {0}", version.Value));
}

唯一需要注意的是,您的查询必须包含一个名为scalar_value的列。

0

实际上,提供者 没有实现可空类型,并且有一个 未解决的问题

虽然可以切换到不同的提供者(如果您知道轻量级替代方案,请建议),但我使用以下方法进行了处理。在我的情况下,我不能简单地避免零(0)值,因为它在数据库中具有特殊含义,我必须将其与无数据区分开来。

public Task<int> GetLastID()
{
    var sRes = RealDatabase.ExecuteScalarAsync<string>
        ("SELECT cast(max(ID) as varchar) FROM DATA)");
    return string.IsNullOrEmpty(sRes) ? null : int.Parse(sRes);

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接