Entity Framework Core操作MySQL如何提取指定ID区间的10条随机记录
EF Core + Pomelo 操作MySQL随机取指定ID区间数据的解决方案
你之前使用的dbContext.MyTable.OrderBy(r => Guid.NewGuid()).Take(10);不生效的核心原因是:Pomelo驱动默认不会将C#的Guid.NewGuid()调用翻译为MySQL原生的RAND()随机函数,排序操作会在内存中执行,无法达到预期效果。
以下是可行的3种实现方案:
方案1:使用内置EF.Functions.Random()(推荐)
Pomelo 3.0及以上版本已内置EF.Functions.Random()的MySQL函数映射,完全兼容LINQ写法,无SQL注入风险:
// 先过滤ID区间,再随机排序取10条 var randomData = dbContext.MyTable .Where(x => x.Id >= 1 && x.Id <= 600) .OrderBy(x => EF.Functions.Random()) .Take(10) .ToList();
方案2:执行原生SQL查询
如果你的Pomelo版本较低不支持方案1,可以直接写MySQL原生语句实现:
注意动态参数要使用参数化写法,避免SQL注入风险
int minId = 1; int maxId = 600; int takeCount = 10; var randomData = dbContext.MyTable .FromSqlRaw(@"SELECT * FROM MyTable WHERE Id BETWEEN {0} AND {1} ORDER BY RAND() LIMIT {2}", minId, maxId, takeCount) .ToList();
方案3:自定义函数映射兼容旧代码
如果你不想修改原有Guid.NewGuid()的写法,可以在DbContext的OnModelCreating方法中配置函数映射:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDbFunction(typeof(Guid).GetMethod(nameof(Guid.NewGuid))) .HasName("RAND") .HasTranslation(_ => new SqlFunctionExpression( "RAND", Enumerable.Empty<SqlExpression>(), nullable: true, argumentsPropagateNullability: Enumerable.Empty<bool>(), typeof(double), null)); }
配置完成后你原有代码即可正常运行。
提示:你筛选的ID区间只有最多600条数据,以上3种方案性能均无问题,可根据你的项目版本灵活选择
内容的提问来源于stack exchange,提问作者Fernando Pereira
相关产品推荐
相关产品推荐

