使用LINQ查询数据库多表是否包含指定字符的实现方法
实现正确性判断及优化方案
正确性判断
你的实现仅在需求为「字段完全等于W或w」时逻辑成立,如果需求是「字段包含W/w字符」,现有实现不满足要求:
代码中unos.Contains(x.Name)的作用是判断x.Name的完整值是否在unos列表中,仅当字段值完全等于W或者w时才会命中,不会匹配Wind、pWe这类包含目标字符的字段值。
可优化点
- 修正匹配逻辑:无需单独维护大小写两套匹配值,直接通过忽略大小写的包含判断实现需求,同时兼容EF的SQL转换规则。
- 空值安全处理:如果
Genre、Album、Album.Artist允许为空,直接访问其属性会触发空引用异常,需要增加非空判断。 - 显式加载关联表:通过
Include+ThenInclude预加载用到的导航属性,避免懒加载触发额外N+1查询,大幅提升性能。 - 减少冗余数据传输:不用查询完整的
Track实体,通过Select投影仅获取需要的4个字段,降低数据库IO和内存占用。
优化后代码示例
var filterChar = "W"; var pesme = _entities.Tracks // 预加载关联表 .Include(x => x.Genre) .Include(x => x.Album) .ThenInclude(x => x.Artist) .Where(x => // 忽略大小写判断包含,IndexOf写法对EF转SQL的兼容性更高 (x.Name != null && x.Name.IndexOf(filterChar, StringComparison.OrdinalIgnoreCase) >= 0) || (x.Genre != null && x.Genre.Name != null && x.Genre.Name.IndexOf(filterChar, StringComparison.OrdinalIgnoreCase) >= 0) || (x.Album != null && x.Album.Title != null && x.Album.Title.IndexOf(filterChar, StringComparison.OrdinalIgnoreCase) >= 0) || (x.Album != null && x.Album.Artist != null && x.Album.Artist.Name != null && x.Album.Artist.Name.IndexOf(filterChar, StringComparison.OrdinalIgnoreCase) >= 0) ) // 仅投影需要的字段 .Select(x => new { TrackName = x.Name ?? string.Empty, AlbumTitle = x.Album != null ? x.Album.Title ?? string.Empty : string.Empty, ArtistName = x.Album != null && x.Album.Artist != null ? x.Album.Artist.Name ?? string.Empty : string.Empty, GenreName = x.Genre != null ? x.Genre.Name ?? string.Empty : string.Empty }) .ToList(); foreach (var p in pesme) { Console.WriteLine($"{p.TrackName}-{p.AlbumTitle}-{p.ArtistName}-{p.GenreName}"); }
如果你的数据库排序规则本身是大小写不敏感的,可以去掉StringComparison参数,直接用x.Name.Contains(filterChar)写法,代码会更简洁。
内容的提问来源于stack exchange,提问作者Luka Vujovic
相关产品推荐
相关产品推荐

