最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# 類型系統(tǒng)上實(shí)現(xiàn)一個 SQL 查詢引擎原型

 更新時間:2026年03月07日 09:19:34   作者:碼云數(shù)智-園園  
在C#類型系統(tǒng)上實(shí)現(xiàn)一個SQL查詢引擎,核心目標(biāo)是利用 C# 的強(qiáng)類型、泛型、表達(dá)式樹(Expression Trees)等特性,構(gòu)建一個類型安全、可組合、可編譯為 SQL 的查詢系統(tǒng),本文介紹C# 類型系統(tǒng)上實(shí)現(xiàn)一個 SQL 查詢引擎,感興趣的朋友一起看看吧

在 C# 類型系統(tǒng)上實(shí)現(xiàn)一個 SQL 查詢引擎,核心目標(biāo)是:利用 C# 的強(qiáng)類型、泛型、表達(dá)式樹(Expression Trees)等特性,構(gòu)建一個類型安全、可組合、可編譯為 SQL 的查詢系統(tǒng)。這類似于 Entity Framework Core 或 LINQ to SQL 的核心機(jī)制。

下面我們將從零開始,逐步設(shè)計并實(shí)現(xiàn)一個簡化但功能完整的 類型化 SQL 查詢引擎原型。

一、目標(biāo)與范圍

我們要實(shí)現(xiàn)的功能:

  • 支持 SELECT, WHERE, ORDER BY, LIMIT
  • 支持基本比較(==, >, <)、邏輯運(yùn)算(&&, ||
  • 支持投影(Select(x => new { x.Id, x.Name })
  • 將 LINQ 表達(dá)式樹翻譯為 SQL 字符串
  • 全程類型安全:編譯時報錯,而非運(yùn)行時

不實(shí)現(xiàn)(簡化):

  • JOIN、GROUP BY、子查詢、聚合函數(shù)
  • 參數(shù)化防注入(但會預(yù)留接口)
  • 復(fù)雜類型映射(僅支持簡單 POCO)

二、整體架構(gòu)設(shè)計

// 1. 實(shí)體類(用戶定義)
public class User 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}
// 2. 查詢?nèi)肟冢篋bSet<T>
var users = new DbSet<User>("users");
// 3. LINQ 風(fēng)格鏈?zhǔn)秸{(diào)用
var query = users
    .Where(u => u.Age > 18)
    .OrderBy(u => u.Name)
    .Select(u => new { u.Id, u.Name })
    .Take(10);
// 4. 生成 SQL
string sql = query.ToSql();
// 輸出: SELECT Id, Name FROM users WHERE Age > 18 ORDER BY Name LIMIT 10

三、核心組件實(shí)現(xiàn)

1.DbSet<T>:查詢起點(diǎn)

public class DbSet<T>
{
    private readonly string _tableName;
    public DbSet(string tableName) => _tableName = tableName;
    public Query<T> Where(Expression<Func<T, bool>> predicate)
        => new Query<T>(_tableName).Where(predicate);
    // 其他方法委托給 Query<T>
}

2.Query<T>:查詢構(gòu)建器(支持鏈?zhǔn)秸{(diào)用)

public class Query<T>
{
    public string TableName { get; }
    public Expression? WhereClause { get; private set; }
    public LambdaExpression? OrderByClause { get; private set; }
    public LambdaExpression? SelectClause { get; private set; }
    public int? Limit { get; private set; }
    internal Query(string tableName) => TableName = tableName;
    public Query<T> Where(Expression<Func<T, bool>> predicate)
    {
        WhereClause = predicate;
        return this;
    }
    public Query<T> OrderBy<TKey>(Expression<Func<T, TKey>> keySelector)
    {
        OrderByClause = keySelector;
        return this;
    }
    public Query<TResult> Select<TResult>(Expression<Func<T, TResult>> selector)
    {
        return new Query<TResult>(TableName)
        {
            WhereClause = WhereClause,
            OrderByClause = OrderByClause,
            SelectClause = selector,
            Limit = Limit
        };
    }
    public Query<T> Take(int count)
    {
        Limit = count;
        return this;
    }
    public string ToSql()
    {
        return SqlTranslator.Translate(this);
    }
}

3.SqlTranslator:表達(dá)式樹 → SQL

這是最核心的部分!我們遍歷表達(dá)式樹,生成 SQL 片段。

public static class SqlTranslator
{
    public static string Translate<T>(Query<T> query)
    {
        var select = BuildSelect(query.SelectClause ?? GetDefaultSelect<T>());
        var from = $"FROM {query.TableName}";
        var where = query.WhereClause != null ? $"WHERE {Visit(query.WhereClause.Body)}" : "";
        var orderBy = query.OrderByClause != null ? $"ORDER BY {GetMemberName(query.OrderByClause.Body)}" : "";
        var limit = query.Limit.HasValue ? $"LIMIT {query.Limit}" : "";
        return $"{select} {from} {where} {orderBy} {limit}".Replace("  ", " ").Trim();
    }
    private static string BuildSelect(LambdaExpression selector)
    {
        if (selector.Body is MemberInitExpression init)
        {
            var members = init.Bindings.OfType<MemberAssignment>()
                .Select(b => b.Member.Name);
            return "SELECT " + string.Join(", ", members);
        }
        else if (selector.Body is ParameterExpression)
        {
            // SELECT * 情況
            return "SELECT *";
        }
        else if (selector.Body is MemberExpression member)
        {
            return $"SELECT {member.Member.Name}";
        }
        throw new NotSupportedException("Unsupported select expression");
    }
    private static string Visit(Expression expr)
    {
        return expr switch
        {
            BinaryExpression bin => VisitBinary(bin),
            MemberExpression mem => mem.Member.Name,
            ConstantExpression con => FormatValue(con.Value),
            MethodCallExpression call => throw new NotSupportedException("Method calls not supported"),
            _ => throw new NotSupportedException($"Expression {expr.NodeType} not supported")
        };
    }
    private static string VisitBinary(BinaryExpression bin)
    {
        var left = Visit(bin.Left);
        var right = Visit(bin.Right);
        var op = bin.NodeType switch
        {
            ExpressionType.Equal => "=",
            ExpressionType.GreaterThan => ">",
            ExpressionType.LessThan => "<",
            ExpressionType.AndAlso => "AND",
            ExpressionType.OrElse => "OR",
            _ => throw new NotSupportedException($"Operator {bin.NodeType} not supported")
        };
        return $"({left} {op} {right})";
    }
    private static string FormatValue(object? value)
    {
        return value switch
        {
            null => "NULL",
            string s => $"'{s.Replace("'", "''")}'", // 簡單轉(zhuǎn)義
            bool b => b ? "1" : "0",
            _ => value.ToString()!
        };
    }
    private static string GetMemberName(Expression expr)
    {
        return expr switch
        {
            MemberExpression m => m.Member.Name,
            UnaryExpression u when u.NodeType == ExpressionType.Convert => GetMemberName(u.Operand),
            _ => throw new ArgumentException("Expected member access")
        };
    }
    private static LambdaExpression GetDefaultSelect<T>()
    {
        var param = Expression.Parameter(typeof(T), "x");
        return Expression.Lambda(param, param);
    }
}

四、使用示例

var users = new DbSet<User>("users");
// 示例 1:完整查詢
var query1 = users
    .Where(u => u.Age > 18 && u.Name == "Alice")
    .OrderBy(u => u.Name)
    .Select(u => new { u.Id, u.Name })
    .Take(5);
Console.WriteLine(query1.ToSql());
// 輸出: SELECT Id, Name FROM users WHERE ((Age > 18) AND (Name = 'Alice')) ORDER BY Name LIMIT 5
// 示例 2:僅 WHERE
var query2 = users.Where(u => u.Id == 100);
Console.WriteLine(query2.ToSql());
// 輸出: SELECT * FROM users WHERE (Id = 100)

五、關(guān)鍵設(shè)計亮點(diǎn)

特性實(shí)現(xiàn)方式優(yōu)勢
類型安全泛型 + 表達(dá)式樹編譯時檢查字段名、類型
鏈?zhǔn)?APIFluent Builder符合 LINQ 習(xí)慣
SQL 生成表達(dá)式樹遍歷避免字符串拼接錯誤
投影支持MemberInitExpression 解析支持匿名對象選擇

六、可擴(kuò)展方向

  1. 參數(shù)化查詢
    • FormatValue 中改為返回參數(shù)占位符(如 @p0),并收集參數(shù)值
  2. JOIN 支持
    • 引入 Join<TOuter, TInner, TResult> 方法,解析 lambda 中的關(guān)聯(lián)條件
  3. 更多運(yùn)算符
    • 支持 Contains(→ IN)、StartsWith(→ LIKE
  4. 方言適配
    • 抽象 ISqlDialect,支持 MySQL/PostgreSQL/SQLite 不同語法
  5. 執(zhí)行層
    • 添加 .ToList(),用 DbCommand 執(zhí)行 SQL 并反序列化結(jié)果

七、為什么這很“C#”?

  • 表達(dá)式樹(Expression Trees) 是 C# 獨(dú)有的強(qiáng)大特性,允許在運(yùn)行時分析代碼結(jié)構(gòu)。
  • 泛型 + 匿名類型 讓投影類型安全且簡潔。
  • LINQ 語法糖 使查詢像寫 SQL 一樣自然,但由編譯器保證正確性。

?? 這正是 Entity Framework、Dapper.Linq 等 ORM 的底層思想!

總結(jié)

我們用 不到 200 行核心代碼,在 C# 類型系統(tǒng)上構(gòu)建了一個:

  • ? 類型安全
  • ? 可組合
  • ? 可翻譯為 SQL
  • ? 支持基本查詢操作

的 SQL 查詢引擎原型。它展示了 如何將語言特性(表達(dá)式樹)與領(lǐng)域問題(SQL 生成)優(yōu)雅結(jié)合——這正是現(xiàn)代 C# 高級庫的設(shè)計精髓。

到此這篇關(guān)于C# 類型系統(tǒng)上實(shí)現(xiàn)一個 SQL 查詢引擎原型的文章就介紹到這了,更多相關(guān)C#  SQL 查詢引擎內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c# 進(jìn)程內(nèi)部的同步

    c# 進(jìn)程內(nèi)部的同步

    這篇文章主要介紹了c# 進(jìn)程內(nèi)部的同步,幫助大家更好的理解和學(xué)習(xí)c#,感興趣的朋友可以了解下
    2020-10-10
  • 利用C#實(shí)現(xiàn)修改圖片透明度功能

    利用C#實(shí)現(xiàn)修改圖片透明度功能

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)修改圖片透明度功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以了解一下
    2022-12-12
  • WPF實(shí)現(xiàn)動畫效果(六)之路徑動畫

    WPF實(shí)現(xiàn)動畫效果(六)之路徑動畫

    這篇文章介紹了WPF實(shí)現(xiàn)動畫效果之路徑動畫,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • c#動態(tài)改變webservice的url訪問地址

    c#動態(tài)改變webservice的url訪問地址

    這篇文章主要介紹了c#動態(tài)改變webservice的url訪問地址,需要的朋友可以參考下
    2014-03-03
  • unity實(shí)現(xiàn)翻頁按鈕功能

    unity實(shí)現(xiàn)翻頁按鈕功能

    這篇文章主要為大家詳細(xì)介紹了unity實(shí)現(xiàn)翻頁按鈕功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C# WinForm創(chuàng)建Excel文件的實(shí)例

    C# WinForm創(chuàng)建Excel文件的實(shí)例

    下面小編就為大家?guī)硪黄狢# WinForm創(chuàng)建Excel文件的實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • 深入理解C#中的Delegate

    深入理解C#中的Delegate

    委托是一種安全地封裝方法的類型,它與 C 和 C++ 中的函數(shù)指針類似。與 C 中的函數(shù)指針不同,委托是面向?qū)ο蟮?、類型安全的和保險的。委托的類型由委托的名稱定義
    2016-07-07
  • C#基于基姆拉爾森算法計算指定日期是星期幾的方法

    C#基于基姆拉爾森算法計算指定日期是星期幾的方法

    這篇文章主要介紹了C#基于基姆拉爾森算法計算指定日期是星期幾的方法,實(shí)例分析了基姆拉爾森算法的原理與使用技巧,非常具有實(shí)用價值,需要的朋友可以參考下
    2015-04-04
  • C#?重寫Notification提示窗口的示例代碼

    C#?重寫Notification提示窗口的示例代碼

    本文主要介紹了C#?重寫Notification提示窗口的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • C#中的反射(System.Reflection)

    C#中的反射(System.Reflection)

    這篇文章介紹了C#中的反射(System.Reflection),文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05

最新評論

汝州市| 高要市| 元江| 晋宁县| 太谷县| 沁阳市| 舒城县| 西宁市| 木兰县| 岑溪市| 荆州市| 萍乡市| 富源县| 西华县| 沐川县| 广东省| 林周县| 道真| 张家川| 积石山| 扬中市| 大城县| 曲水县| 礼泉县| 常山县| 增城市| 水富县| 益阳市| 化德县| 清流县| 修水县| 桃源县| 新邵县| 宜阳县| 北碚区| 固阳县| 射阳县| 鄂伦春自治旗| 沙田区| 湘乡市| 高淳县|