You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过自定义SQL查询将IQueryable转换为IEnumerable?

当然有可行的方法,但得先明确你的场景——从示例代码看,你用的是内存中的IQueryable(通过List.AsQueryable()生成的),而不是连接数据库的IQueryable(比如EF Core的DbSet)。这两种场景的处理方式不一样,下面给你针对性的解决方案:

针对内存IQueryable的解决方案

你的数据源是内存中的集合,原生SQL语法没法直接被LINQ to Objects解析,所以需要转个弯处理:

方案1:解析SQL转换为LINQ表达式

如果你的SQL比较简单(比如示例里的单条件WHERE查询),可以手动解析SQL中的条件,然后用LINQ表达式树构建过滤逻辑,最后转成IEnumerable。

比如给IQueryable写个扩展方法:

public static IEnumerable<T> ConvertToIEnumerable<T>(this IQueryable<T> source, string sql)
{
    // 仅针对示例中的简单SQL做解析,复杂SQL需要更完善的解析逻辑
    if (sql.StartsWith("SELECT * FROM c WHERE c.ID = "))
    {
        // 提取ID值(注意处理单引号)
        var idValue = sql.Substring("SELECT * FROM c WHERE c.ID = ".Length).Trim('\'');
        
        // 用表达式树构建Where条件
        var parameter = Expression.Parameter(typeof(T), "c");
        var idProperty = Expression.Property(parameter, "ID");
        var constantValue = Expression.Constant(idValue);
        var equalExpr = Expression.Equal(idProperty, constantValue);
        var filterLambda = Expression.Lambda<Func<T, bool>>(equalExpr, parameter);
        
        // 过滤后转成IEnumerable
        return source.Where(filterLambda).AsEnumerable();
    }
    
    // 其他SQL场景可以扩展解析逻辑,默认返回全部数据
    return source.AsEnumerable();
}

这个方法的好处是性能高,不需要额外依赖,但缺点是只能处理简单SQL,复杂的JOIN、GROUP BY等语法很难解析。

方案2:用内存数据库执行原生SQL

如果需要支持复杂的SQL语法,可以把内存数据导入到内存数据库(比如SQLite内存模式),然后执行原生SQL查询,最后把结果转成IEnumerable。

示例代码如下:

using Microsoft.Data.Sqlite;
using System.Data;

public static IEnumerable<Book> ConvertToIEnumerable(this IQueryable<Book> source, string sql)
{
    // 创建内存SQLite连接
    using var connection = new SqliteConnection("Data Source=:memory:");
    connection.Open();
    
    // 创建对应的数据表
    using var createTableCmd = connection.CreateCommand();
    createTableCmd.CommandText = "CREATE TABLE Book (ID TEXT, Title TEXT)";
    createTableCmd.ExecuteNonQuery();
    
    // 将内存中的Book数据导入到SQLite表
    var dataTable = new DataTable();
    dataTable.Columns.Add("ID", typeof(string));
    dataTable.Columns.Add("Title", typeof(string));
    foreach (var book in source)
    {
        dataTable.Rows.Add(book.ID, book.Title);
    }
    
    using var bulkCopy = new SqliteBulkCopy(connection);
    bulkCopy.DestinationTableName = "Book";
    bulkCopy.WriteToServer(dataTable);
    
    // 执行传入的SQL查询
    using var queryCmd = connection.CreateCommand();
    queryCmd.CommandText = sql;
    using var reader = queryCmd.ExecuteReader();
    
    // 读取结果并转换为Book集合
    var result = new List<Book>();
    while (reader.Read())
    {
        result.Add(new Book
        {
            ID = reader.GetString(0),
            Title = reader.GetString(1)
        });
    }
    
    return result;
}

这个方法能支持几乎所有SQL语法,但会有一定的性能开销(毕竟要把数据导入内存数据库),适合数据量不大的场景。

额外说明:如果是数据库IQueryable(比如EF Core)

如果你的IQueryable是来自EF Core的DbSet(连接真实数据库),那处理起来更简单——直接用EF Core的FromSqlRaw或FromSqlInterpolated方法执行原生SQL,然后调用AsEnumerable()转成IEnumerable:

// 假设dbContext是你的EF Core上下文
var id = "123";
string queryString = "SELECT * FROM Book WHERE ID = {0}";
var expected = dbContext.Books.FromSqlRaw(queryString, id).AsEnumerable();

内容的提问来源于stack exchange,提问作者superninja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:17:04