三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Dommel源代码解析:SqlExpression类如何构建动态查询

Dommel源代码解析:SqlExpression类如何构建动态查询

Dommel源代码解析:SqlExpression类如何构建动态查询

【免费下载链接】DommelCRUD operations with Dapper made simple.项目地址: https://gitcode.com/gh_mirrors/do/Dommel

Dommel是一个让Dapper的CRUD操作变得简单的开源项目,其核心功能之一就是通过SqlExpression类实现动态查询构建。本文将深入解析SqlExpression类的工作原理,帮助开发者理解如何利用它来创建灵活高效的SQL查询。

SqlExpression类的核心功能

SqlExpression 是Dommel项目中的关键类,位于 src/Dommel/SqlExpression.cs文件中。它的主要作用是将LINQ表达式转换为对应的SQL语句,同时处理参数化查询以防止SQL注入。

这个泛型类提供了一系列方法来构建SQL查询的各个部分,包括SELECT、WHERE、ORDER BY、GROUP BY和分页等。通过链式调用这些方法,开发者可以轻松构建复杂的查询语句,而无需手动拼接SQL字符串。

动态查询构建的工作流程

SqlExpression类构建动态查询的过程可以分为以下几个关键步骤:

1. 初始化与配置

SqlExpression的构造函数需要一个ISqlBuilder实例,用于生成特定数据库类型的SQL语法。这使得Dommel能够支持多种数据库,如SQL Server、MySQL、PostgreSQL等。

public SqlExpression(ISqlBuilder sqlBuilder) { SqlBuilder = sqlBuilder; }

2. 构建SELECT子句

Select方法是构建查询的起点,它支持三种方式:选择所有列、选择特定列或使用自定义SQL表达式。

例如,选择所有列:

public virtual SqlExpression<TEntity> Select() { _selectQuery = $"select * from {Resolvers.Table(typeof(TEntity), SqlBuilder)}"; return this; }

3. 处理WHERE条件

Where方法是SqlExpression最强大的功能之一,它能够将Lambda表达式转换为SQL的WHERE子句。这涉及到对表达式树的解析和转换。

public virtual SqlExpression<TEntity> Where(Expression<Func<TEntity, bool>>? expression) { if (expression != null) { AppendToWhere("and", expression); } return this; }

4. 生成最终SQL

ToSql方法负责将各个部分组合成完整的SQL语句,并处理参数化:

public string ToSql() { var query = ""; if (!string.IsNullOrEmpty(_selectQuery)) { query += _selectQuery; } // 处理WHERE、ORDER BY、GROUP BY和分页等子句 // ... return query; }

表达式树解析的关键技术

SqlExpression类的核心在于其对Lambda表达式的解析能力。VisitExpression方法是这一过程的入口,它根据不同的表达式类型调用相应的处理方法:

protected virtual object VisitExpression(Expression expression) => expression.NodeType switch { ExpressionType.Lambda => VisitLambda((LambdaExpression)expression), ExpressionType.LessThan or ExpressionType.LessThanOrEqual or ExpressionType.GreaterThan or ExpressionType.GreaterThanOrEqual or ExpressionType.Equal or ExpressionType.NotEqual or ExpressionType.And or ExpressionType.AndAlso or ExpressionType.Or or ExpressionType.OrElse => VisitBinary((BinaryExpression)expression), // 处理其他表达式类型 // ... _ => expression, };

例如,VisitBinary方法处理比较操作符,将其转换为对应的SQL操作符:

protected virtual string GetOperant(ExpressionType expressionType) => expressionType switch { ExpressionType.Equal => "=", ExpressionType.NotEqual => "<>", ExpressionType.GreaterThan => ">", ExpressionType.GreaterThanOrEqual => ">=", ExpressionType.LessThan => "<", ExpressionType.LessThanOrEqual => "<=", // 其他操作符映射 // ... _ => expressionType.ToString(), };

参数化查询的实现

为了防止SQL注入并提高查询性能,SqlExpression类使用了参数化查询。AddParameter方法负责创建参数并添加到查询中:

protected virtual void AddParameter(object value, out string paramName) { _parameterIndex++; paramName = SqlBuilder.PrefixParameter($"p{_parameterIndex}"); _parameters.Add(paramName, value: value); }

实际应用示例

使用SqlExpression构建查询的典型示例如下:

var sqlExpression = new SqlExpression<Customer>(new SqlServerSqlBuilder()) .Select(c => new { c.Id, c.Name }) .Where(c => c.Age > 18 && c.City == "Beijing") .OrderBy(c => c.Name); string sql = sqlExpression.ToSql(out var parameters);

这将生成类似以下的SQL语句:

select [Id], [Name] from [Customers] where [Age] > @p1 and [City] = @p2 order by [Name] asc

总结

SqlExpression类是Dommel项目实现动态查询的核心组件,它通过解析Lambda表达式树,将其转换为类型安全的SQL语句。这种方式不仅提高了开发效率,还增强了代码的可读性和可维护性,同时有效防止了SQL注入攻击。

通过深入理解SqlExpression的工作原理,开发者可以更好地利用Dommel进行数据库操作,甚至可以根据自己的需求扩展其功能。Dommel的源代码结构清晰,设计优雅,是学习表达式树解析和动态SQL生成的优秀范例。

【免费下载链接】DommelCRUD operations with Dapper made simple.项目地址: https://gitcode.com/gh_mirrors/do/Dommel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

← 返回列表