Ошибка сродства типа SQLiteDataReader? - PullRequest
0 голосов
/ 30 ноября 2018

SQLite может хранить значение любого типа в столбце любого другого типа.Когда я пытаюсь прочитать такое значение другого типа из приложения .net с помощью SQLiteDataReader, оно выполняет преобразование в столбец определенного типа, даже если я пытаюсь прочитать его как объект.Вот пример:

using System;
using System.Data.SQLite;

namespace SqliteTypeAffinityTest
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var connection = new SQLiteConnection("Data Source=:memory:"))
            {
                // advise from @Shawn to use NoVerifyTypeAffinity does not help, neither separate nor combined with default

                // connection.Flags = SQLiteConnectionFlags.NoVerifyTypeAffinity;
                // connection.Flags = connection.Flags | SQLiteConnectionFlags.NoVerifyTypeAffinity;

                connection.Open();

                using (var cmd = new SQLiteCommand(connection))
                {
                    cmd.CommandText = "CREATE TABLE t(b BLOB)";
                    cmd.ExecuteNonQuery();

                    cmd.CommandText = "INSERT INTO t(b) VALUES (x'FF')";
                    cmd.ExecuteNonQuery();

                    cmd.CommandText = "INSERT INTO t(b) VALUES ('FF')";
                    cmd.ExecuteNonQuery();

                    cmd.CommandText = "SELECT b, typeof(b) AS type FROM t";
                    using (var reader = (SQLiteDataReader)cmd.ExecuteReader())
                    {
                        reader.Read();

                        object t1 = reader.GetValue(0);
                        string sqliteType1 = reader.GetString(1);

                        reader.Read();

                        object t2 = reader.GetValue(0);
                        string sqliteType2 = reader.GetString(1);

                        Type netType1 = t1.GetType();
                        Type netType2 = t2.GetType();

                        Console.WriteLine("sqlite type #1: {0}, .net type #1: {1}", sqliteType1, netType1);
                        Console.WriteLine("sqlite type #2: {0}, .net type #2: {1}", sqliteType2, netType2);
                    }
                }
            }

            Console.WriteLine("done");
            Console.Read();
        }
    }
}

Вывод на консоль будет выглядеть следующим образом:

sqlite type #1: blob, .net type #1: System.Byte[]
sqlite type #2: text, .net type #2: System.Byte[]

Обратите внимание, что .net типом # 2 является System.Byte [] (однако тип SQLite является текстовым!), ОднакоЯ ожидаю, что это будет System.String.

Есть ли способ прочитать это значение как строку?Я понимаю, что могу также запросить тип значения, как в моем примере, и выполнить некоторое преобразование после прочтения, но я бы хотел этого избежать.

РЕДАКТИРОВАТЬ # 1, чтобы быть более правильным в моем вопросе после ответа @MikeT.Я не ищу способ прочитать столбец как строку.Мне нужно прочитать каждое значение с его собственным типом.Так что в моем примере t1 должен оставаться как byte [], но t2 должен быть строкой.Я обновил свой пример, чтобы сделать его более явным (ранее была 1 строка с двумя столбцами BLOB).

РЕДАКТИРОВАТЬ # 2, включая полный текст теста с использованием, чтобы сделать более очевидной используемую библиотеку и сделать ее более удобнойвоспроизведение

1 Ответ

0 голосов
/ 30 ноября 2018

Blob часто плохо представлены сторонними инструментами SQLite.Тем не менее, я считаю, что использование hex(the_value) сделает их достаточно читабельными (sic).

Например, рассмотрим таблицу (текст и блоб в одном столбце, особенно для Джона :)): -

enter image description here

с использованием (ошибочно из-за дат): -

SELECT hex(data) FROM convdt;

Выход: -

enter image description here

PS, вставленный с использованием x'FF00FE01FD02 '(в столбец со сходством типов в качестве текста) - Вы можете использовать функцию quote для возврата X'FF00FE01FD02'

Или использовать различные типы столбцов: -

SELECT typeof(data), CASE WHEN typeof(data) = 'blob' THEN hex(data) ELSE data END AS data FROM convdt;

и получить: -

enter image description here

...