Как я могу прочитать «uuid» из столбца в базе данных sqlite3, используя sqlite-net-pcl в Xamarin Forms

У меня есть схема базы данных, которую я не контролирую (это файл sqlite3, экспортированный из настольного приложения, с которым мне нужно взаимодействовать), который содержит UUID для некоторых столбцов. Я использую sqlite-net-pcl в приложении Xamarin.Forms и не могу понять, как успешно читать эти столбцы. Вот что я пробовал:

  • с помощью командной строки sqlite3 я подтвердил, что схема имеет тип uuid для соответствующего столбца, а с помощью select count(distinct uuidcolumn) from mytable; я подтвердил наличие значений для каждой строки. (Столбец может принимать значения NULL, что относится к приведенному ниже фрагменту кода, но на практике все строки имеют ненулевые значения)
  • У меня есть этот объект модели:
namespace brahms.Model
{
    [Table("mytable")]
    public class MyTable
    {
        [Column("uuidcolumn")]
        public Guid UUIDColumn { get; }

        [PrimaryKey, AutoIncrement, NotNull]
        [Column("recordid")]
        public int RecordID { get; set; }
    }
}
  • если я извлекаю объект с помощью database.Query<MyTable>() запросов, UUIDColumn всегда равно Guid.Empty.
  • Я попытался переключить тип в определении класса на Byte[]; это всегда null.
  • Я попытался переключить тип в определении класса на string; это всегда null.
  • То же самое относится и к типу UInt16[] (GUID может храниться как большой двоичный объект из 16-битных слов, поэтому я пробовал и этот тип).

Как я могу прочитать значения в столбцах с типом uuid, используя sqlite-net-pcl?


person Graham Lee    schedule 23.02.2021    source источник
comment
каков фактический тип столбца в БД?   -  person Jason    schedule 23.02.2021
comment
@Jason Джейсон, тип указан в схеме только как uuid, я читал, что на самом деле не существует типа uuid но я не знаю, что это значит. Я бы предположил blob, так как я не могу читать содержимое в виде строк, но я также не могу читать его в виде байтов.   -  person Graham Lee    schedule 23.02.2021
comment
Мысль blob натолкнула меня на мысль попробовать UInt16[] в качестве сопоставленного типа, что тоже не работает.   -  person Graham Lee    schedule 23.02.2021
comment
похоже, что байт [] - правильный подход - github.com/praeclarum/sqlite-net /вопросы/412   -  person Jason    schedule 23.02.2021
comment
@ Джейсон Я так и думал, не знаю, почему это не работает в моем случае. Обычно я запускаю тестовый проект с минимальным воспроизведением, но, поскольку я не контролирую схему, я не могу сделать большую минимизацию :-(   -  person Graham Lee    schedule 23.02.2021


Ответы (1)


Я отказался от использования функций ORM в sqlite-net-pcl и использовал этот запрос:

db.executeScalar<byte[]>('select hex(uuidcolumn) from mytable where recordid=1');

В ответ я получаю 72 байта, которые представляют собой 36 символов ASCII в строковом представлении Guid (время от времени один из символов равен 2D, что соответствует - в наборе ASCII). Поэтому я думаю, что резервное хранилище — это большой двоичный объект, в котором хранится текстовое представление Guid, что странно, но я смогу восстановить Guid отсюда.

Используя этот ответ и получив этот блоб в виде строки, я получил следующую реализацию:

        public Guid GetUUIDColumn()
        {
            string dbRep = _database.ExecuteScalar<string>("select hex(uuidcolumn) from mytable where recordid = ?", RecordID);
            if (dbRep == null || dbRep == string.Empty) return Guid.Empty;
            var bytes = new byte[dbRep.Length / 2];
            // each pair of bytes represents the ASCII code (in hexadecimal) for a character in the string representation of a Guid.
            for (var i = 0; i < bytes.Length; i++)
            {
                bytes[i] = Convert.ToByte(dbRep.Substring(i * 2, 2), 16);
            }

            string asString = Encoding.ASCII.GetString(bytes);
            return new Guid(asString);  
        }
person Graham Lee    schedule 24.02.2021