与@Fabian Monkemoller 不同,我无法让@User1 的代码立即工作。这是一个修改版本,它利用可空引用类型和方法嵌套将主代码与 try-catch 块分开:
public static object?[][]? ToDataSet(this SQLiteConnection sqlConnection, string query , bool includeColumnNamesAsFirstRow = true)
{
var stQuery = SQLite3.Prepare2(sqlConnection.Handle, query );
var colLength = SQLite3.ColumnCount(stQuery);
try
{
return SelectRows().ToArray();
}
catch (Exception e)
{
return null;
}
finally
{
if (stQuery != null)
{
SQLite3.Finalize(stQuery);
}
}
IEnumerable<object?[]> SelectRows()
{
if (includeColumnNamesAsFirstRow)
{
yield return SelectColumnNames(stQuery, colLength).ToArray();
}
while (SQLite3.Step(stQuery) == SQLite3.Result.Row)
{
yield return SelectColumns(stQuery, colLength).ToArray();
}
static IEnumerable<object> SelectColumnNames(SQLitePCL.sqlite3_stmt stQuery, int colLength)
{
for (int i = 0; i < colLength; i++)
{
yield return SQLite3.ColumnName(stQuery, i);
}
}
static IEnumerable<object?> SelectColumns(SQLitePCL.sqlite3_stmt stQuery, int colLength)
{
for (int i = 0; i < colLength; i++)
{
var x = SQLitePCL.raw.sqlite3_column_decltype(stQuery, i);
yield return x switch
{
"text" => SQLite3.ColumnString(stQuery, i),
"integer" => SQLite3.ColumnInt(stQuery, i),
"bigint" => SQLite3.ColumnInt64(stQuery, i),
"real" => SQLite3.ColumnDouble(stQuery, i),
"blob" => SQLite3.ColumnBlob(stQuery, i),
"null" => null,
_ => throw new Exception($"Unexpected type encountered in for query {stQuery}")
};
}
}
}
}