SQLite与EF6使用GUID主键时的异常查询问题
问题根源:SQLite与EF的Guid格式不匹配
这个问题的核心在于SQLite没有原生的GUID数据类型,而EF(配合SQLite CodeFirst)对Guid的默认存储格式,和你代码中使用的Guid字符串格式不一致,导致查询时无法匹配。
具体原因拆解:
- SQLite的Guid存储逻辑:当EF将Guid类型映射到SQLite时,默认会把Guid转换成小写、无连字符的字符串(比如
d46d98f3c262468a9c2883d81080cf18)或者二进制数据存储到数据库中。 - 你的代码中的Guid格式:你在
Entity类里用带连字符的大写Guid字符串初始化(D46D98F3-C262-468A-9C28-83D81080CF18),查询时也是用这个格式的Guid值。 - 上下文缓存的干扰:
- 第一个上下文里的
Find能找到数据,是因为它先从上下文的内存缓存中读取,而不是直接查数据库; - 当你先调用
ToArrayAsync加载所有数据到缓存后,Find同样优先查缓存所以能找到,但LINQ的Where语句会生成SQL直接查询数据库,因为格式不匹配所以查不到; - 新上下文没有缓存,不管用
Find还是LINQ都会查数据库,自然找不到数据。
- 第一个上下文里的
解决方法
最可靠的方式是显式配置Guid的转换规则,让EF在存储和查询时统一格式:
修改MyDbContext的OnModelCreating方法,为Entity.Id属性指定转换逻辑:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { Database.SetInitializer(new SqliteDropCreateDatabaseWhenModelChanges<MyDbContext>(modelBuilder)); // 配置Guid存储为无连字符的字符串,查询时自动转换 modelBuilder.Entity<Entity>() .Property(e => e.Id) .HasConversion( guid => guid.ToString("N"), // 存储时转成无连字符的字符串 str => Guid.Parse(str) // 查询时将字符串转回Guid ); }
这样无论你用什么格式初始化Guid,EF都会统一转换成无连字符的字符串存储,查询时也会自动匹配数据库中的格式,就能解决查询不到的问题。
为什么string/int类型正常?
当主键是string或int时,不存在格式转换的问题:
- string类型会原封不动存储你传入的字符串,查询时直接匹配;
- int类型是SQLite原生支持的数值类型,匹配逻辑简单直接,不会出现格式不兼容的情况。
内容的提问来源于stack exchange,提问作者Wernfried
相关产品推荐
相关产品推荐

