Как поставщик SQLite Entity Framework 6 обрабатывает Guids?

Я переношу базу данных нашего продукта на SQLite из другого продукта, поддерживающего Guids. Как мы знаем, SQLite не поддерживает Guids. Я создал модель Entity Framework 6 из своей базы данных (сначала базу данных), и мне нужно создать запрос из С#, который сравнивает Guid с переданным из кода.

Дело в том, что я не могу найти никакой документации о том, как провайдер SQLite Entity Framework обрабатывает Guids. Поиск в сети тоже ничего полезного для меня не нашел. Просто вопросы об использовании Entity Framework с SQLite.

Может ли кто-нибудь указать мне на документацию или, может быть, рассказать мне, как работать с Guids в базе данных SQLite через модель EF6?


person Tony Vitabile    schedule 03.12.2014    source источник
comment
SQLite не имеет явного GUID типа столбца, но сохранение их с привязкой типа BLOB работает отлично. Не много знаю об Entity Framework, но кажется, что преобразователи типов (помимо перечислений) будут только в EF 7. Но GUID имеет CTor из массива байтов и т. д., так что это может быть довольно просто.   -  person peterchen    schedule 03.12.2014
comment
Я храню их как BLOB в своей модели, однако у меня есть проблема. В коде есть выражение, похожее на ID == Guid('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'), которое вызывает исключение, потому что тип ID в базе данных - Byte[], а справа - Guid. Рассматриваемый код должен работать на нашем клиенте (код, над которым я работаю) с SQLite и на нашем сервере, где база данных — это SQL Server. Строка выражения не может измениться. Мне нужно что-то сделать на стороне SQLite, чтобы сравнение работало. Я просто не знаю, что. Вот почему я ищу документацию.   -  person Tony Vitabile    schedule 03.12.2014
comment
В SQLite вы можете переопределить функцию Guid(): sqlite.org/c3ref/create_function.html (хотя не знаю, как это работает через EF)   -  person peterchen    schedule 03.12.2014
comment
Эта функция Guid() не работает в SQLite. Он запускается в поставщике SQLite Entity Framework для преобразования строки в Guid. Затем провайдер отправляет SQL-запрос, который сравнивает значение в столбце с Guid. Проблема в том, что поставщику EF не нравится выражение, потому что тип столбца в EF — byte[], но сравниваемый объект — Guid.. Кажется, я не могу найти никакой документации, а отсутствие поддержки Guid меня убивает.   -  person Tony Vitabile    schedule 03.12.2014
comment
Вы нашли решение? У меня сейчас такая же проблема...   -  person Daniel Sklenitzka    schedule 15.12.2014
comment
У меня пока нет решения. Я собираюсь попробовать что-то вроде "ID == new byte[] { 0xXX, 0xYY . . . } и посмотреть, сработает ли это. Если это сработает, мне придется написать код, который анализирует строку условия и преобразует ее в указанный выше формат. Сейчас я работаю над другими вещами и скоро вернусь к этому. Если вы попробуете это и заставите его работать, опубликуйте его как свой ответ, и я дам вам +1. Если это сработает и для меня, я проверю ваш ответ как ответ.   -  person Tony Vitabile    schedule 15.12.2014
comment
Я использую Guids без проблем с EF6 и System.Data.SQLite 1.0.94. У сущностей есть свойства типа Guid, а в базе данных есть столбцы типа uniqueidentifier, которых, очевидно, не существует в SQLite. Однако при использовании select typeof(GUID) столбцы выглядят как капли.   -  person kjbartel    schedule 06.01.2015


Ответы (2)


Похоже, что это было решено в 1.0.95, но снова сломалось в 1.0.97. Решение состоит в том, чтобы установить для свойства BinaryGUID в строке подключения значение true и установить следующую переменную среды (перед подключением)

Environment.SetEnvironmentVariable("AppendManifestToken_SQLiteProviderManifest",";BinaryGUID=True;");

Источник данных = c:\mydb.db; Версия = 3; BinaryGUID = True;

https://www.connectionstrings.com/sqlite/

person Greg    schedule 07.07.2015
comment
Я использую 1.0.97, но установка переменной среды фактически ломает ее для меня. Я получаю System.Data.Entity.Core.ProviderIncompatibleException : The provider did not return a ProviderManifest instance. и внутреннее исключение System.ArgumentException : An entry with the same key already exists.. Однако прекрасно работает только изменение строки подключения. - person Thorarin; 24.07.2015
comment
Отличный пост! Это решило проблему для меня с использованием 1.0.99 и Entity Framework 6. - person RichTurner; 26.01.2016
comment
BinaryGUID=True в конфигурационном файле — это все, что мне нужно было сделать. - person CrusherJoe; 26.09.2016
comment
BinaryGUID сегодня включен по умолчанию. Я был вынужден отключить его, чтобы иметь рабочие запросы. - person SeriousM; 17.05.2017
comment
Двоичный GUID=истина; или BinaryGUID=false работает для меня, установка его вместе с переменной среды вызывает упомянутый An entry with the same key already exists - person Davi Fiamenghi; 11.02.2020

Наконец-то у меня есть ответ на эту проблему.

Моя проблема в том, что провайдер SQLite Entity Framework 6 не обрабатывает должным образом преобразование литеральных Guids в вашем коде в SQL. То есть выражение Linq вида

context.MyEntity.Where( x => x.GuidColumn == new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") )

Преобразуется в следующий SQL:

SELECT GuidColumn, Column1, Column2, . . . Column n
FROM MyEntity AS Extent1
WHERE Extent1.GuidColumn = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Это неправильно, поскольку значение, хранящееся в столбце, представляет собой массив байтов.

Судя по этому отчету о проблеме на сайте SQLite, оказывается что команда SQLite считает это ошибкой в ​​провайдере и работает над ее исправлением в выпуске 1.0.95.0. Я не знаю, когда это будет выпущено, но, по крайней мере, они признают это проблемой и собираются это исправить.

person Tony Vitabile    schedule 08.01.2015
comment
Это плохо... из-за этой проблемы мы решили хранить GUID в виде строк. - person Aleksei Poliakov; 16.06.2017
comment
Хотя я больше не работаю в этой компании и больше не имею доступа к этой кодовой базе, я думаю, что мы поместили Guid в переменную Guid и сравнили с ней. Насколько я помню, это обрабатывается правильно. - person Tony Vitabile; 21.06.2017