Запрос метаданных Sqlite не работает с Microsoft.Data.Sqlite, работает с System.Data.SQLite
У меня есть простой запрос, взятый непосредственно из документации Microsoft (см. https://docs.microsoft.com/en-us/dotnet/standard/data/sqlite/metadata), который не работает. Согласно документации, запросы противsqlite_master
должны работать, как задумано, но выдают исключения даже после того, как я создаю базу данных и создаю таблицу.
SELECT t.name AS tbl_name, c.name, c.type, c.[notnull], c.dflt_value, c.pk FROM sqlite_master AS t, pragma_table_info(t.name) AS c WHERE t.type = 'table';
Вот изолированный код, выделяющий проблему:
using System;
using System.Data;
using Microsoft.Data.Sqlite;
namespace Test.Library
{
class Program
{
static void Main(string[] args)
{
try
{
string connStr = "Data Source=test.db";
string tableQuery = "CREATE TABLE IF NOT EXISTS 'company' (id Integer PRIMARY KEY AUTOINCREMENT NOT NULL , name Text COLLATE NOCASE , postal Integer);";
string metadataQuery = "SELECT t.name AS tbl_name, c.name, c.type, c.[notnull], c.dflt_value, c.pk FROM sqlite_master AS t, pragma_table_info(t.name) AS c WHERE t.type = 'table';";
using (SqliteConnection conn = new SqliteConnection(connStr))
{
conn.Open();
DataTable result = Query(tableQuery, conn);
Console.WriteLine(result.Rows.Count);
result = Query(metadataQuery, conn);
Console.WriteLine(result.Rows.Count);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.ReadLine();
}
private static DataTable Query(string query, SqliteConnection conn)
{
using (SqliteCommand cmd = new SqliteCommand(query, conn))
{
using (SqliteDataReader rdr = cmd.ExecuteReader())
{
DataTable result = new DataTable();
result.Load(rdr);
return result;
}
}
}
}
}
И вывод консоли, включая исключение (обратите внимание, что первая строка - это Console.WriteLine количества строк, возвращенных при выполнении первого запроса, т.е. 0
)...
0
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table column: pragma_table_info.name'.
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteDataReader.GetSchemaTable()
at System.Data.ProviderBase.SchemaMapping..ctor(DataAdapter adapter, DataSet dataset, DataTable datatable, DataReaderContainer dataReader, Boolean keyInfo, SchemaType schemaType, String sourceTableName, Boolean gettingData, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.FillMappingInternal(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.FillMapping(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
at System.Data.DataTable.Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler)
at System.Data.DataTable.Load(IDataReader reader)
at Test.Library.Program.Query(String query, SqliteConnection conn) in C:\Code\Misc\Program.cs:line 43
at Test.Library.Program.Main(String[] args) in C:\Code\Misc\Program.cs:line 24
Обратите внимание, что metadataQuery
находится прямо с сайта Microsoft (ссылка выше).
Когда я выполняю этот же запрос с помощью DB Browser для Sqlite (или аналогичного), он работает нормально, и при использовании того же кода с System.Data.SQLite
он работает нормально (очевидно, что имена классов имеют немного разные заглавные буквы и т. д.).
Благодарность!
1 ответ
Похоже, проблема в том, как Microsoft.Data.Sqlite обрабатывает запросы данных. directly
из функций, возвращающих табличное значение, таких как pragma_table_info.
С другой стороны, чтобы точно получить всю информацию о метаданных всех таблиц, работает следующий запрос (протестирован с nuget version 3.1.4
)
string metadataQuery = "DROP TABLE IF EXISTS info;" +
"CREATE TEMPORARY TABLE info AS SELECT t.name AS tbl_name, c.name, c.type, c.[notnull], c.dflt_value, c.pk FROM sqlite_master AS t, pragma_table_info(t.name) AS c WHERE t.type = 'table';" +
"SELECT * FROM info";
Информацию об аналогичных проблемах см. Здесь.
Кроме того, Microsoft.Data.Sqlite имеет limitations
при получении информации о схеме.