SQLite Entity Framework 6提供程序如何处理Guids?

14

我正在将我们产品的数据库从另一个支持Guids的产品迁移到SQLite。众所周知,SQLite不支持Guids。我已经从我的数据库中创建了一个实体框架6模型(数据库优先),现在我需要使用C#构建一个查询,以将传递自代码的Guid与其进行比较。

问题是我找不到任何有关SQLite Entity Framework提供程序如何处理Guids的文档。网络搜索也没有找到对我有用的信息,只有关于使用Entity Framework和SQLite的问题。

是否有人能指向相关文档,或者告诉我如何通过EF6模型在SQLite数据库中使用Guids?


SQLite没有明确的列类型GUID,但使用类型亲和性“BLOB”存储它们完全没有问题。我不太了解Entity Framework,但似乎类型转换器(除枚举外)仅在EF 7中存在。但是GUID具有从字节数组等构造函数,因此可能非常简单。 - peterchen
我在我的模型中将它们存储为BLOBs,但是我有一个问题。代码有一个类似于“ID == Guid('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')”的表达式,因为数据库中ID的类型是Byte[],而右侧的内容是Guid,所以会抛出异常。相关代码必须在我们的客户端(我正在处理的代码)上使用SQLite运行,在我们的服务器上,数据库是SQL Server。表达式字符串不能更改。我必须在SQLite方面做一些事情才能使比较工作。我只是不知道该怎么做。这就是为什么我正在寻找文档的原因。 - Tony Vitabile
在SQLite中,您可以覆盖Guid()函数:https://www.sqlite.org/c3ref/create_function.html(不确定如何通过EF实现) - peterchen
“Guid()”函数在SQLite中无法运行。它在SQLite Entity Framework提供程序中运行,将字符串转换为Guid。然后,提供程序会发出SQL查询,将列中的值与Guid进行比较。问题在于EF提供程序不喜欢表达式,因为EF中的列类型是byte[],但要比较的内容是Guid。我似乎找不到任何文档,缺乏Guid支持让我很苦恼。 - Tony Vitabile
你找到解决方案了吗?我现在也遇到了同样的问题... - Daniel Sklenitzka
显示剩余2条评论
2个回答

13

似乎这个问题在1.0.95中得到了解决,但是在1.0.97中再次出现了问题。 解决方法是将连接字符串上的BinaryGUID属性设置为true,并设置以下环境变量(在进行连接之前)

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

Data Source=c:\mydb.db;Version=3;BinaryGUID=True;

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


2
我正在使用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.。然而,只更改连接字符串就可以正常工作。 - Thorarin
1
很棒的帖子!使用1.0.99和Entity Framework 6,这解决了我的问题。 - RichTurner
1
在配置文件中设置BinaryGUID=True就可以了。 - CrusherJoe
二进制 GUID 今天默认开启。我被迫禁用它才能使查询正常工作。 - SeriousM
BinaryGUID=true; 或 BinaryGUID=false 对我有效,将其与环境变量一起设置会导致出现“已存在具有相同键的条目”的问题。 - Davi Fiamenghi
BinaryGUID=true;就足够了。它使用GUID正确地检索数据。 - Serlok

4
我很高兴能够回答这个问题。
我的问题是,SQLite Entity Framework 6提供程序无法正确地将代码中的文字Guid转换为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团队认为这是提供程序中的一个bug,并正在努力在1.0.95.0版本中修复。我不知道何时会发布该版本,但至少他们意识到了这个问题并准备解决它。


1
很遗憾...由于这个问题,我们决定将GUID存储为字符串。 - Aleksei Poliakov
虽然我已经不在那家公司工作,也无法访问那个代码库了,但我认为我们所做的是将Guid放入一个Guid变量中,并与之进行比较。据我记得,这个处理是正确的。 - Tony Vitabile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接