Powerful ram expression to Sql class library - Lambda of SqlSugar hiding function

Usage scenario

1. Lambda to sql has always been one of the most difficult functions in orm. If there is a ready-made parsing library, the difficulty of writing an ORM by yourself will be greatly reduced

2. Lambda is used as a KEY for caching operations, especially in the warehousing mode. Expression parsing is needed to get expressions for general query caching

3. Learning enthusiasts, if you can have a deeper understanding of how Lambda is interpreted into Sql, your understanding of Lambda will go to a higher level, not just in use

 

advantage

In addition to its own ORM function, SqlSugar is also a powerful lambda parser, and is a unique lambda to Sql class library in the market

SqlSugar is not only small, but also has very good performance. It is not inferior to Dapper or even better. As for performance, it is very unreliable to look at other people's evaluation. You can only know it after you use it and test it yourself

1. High performance} expression parsing speed is much faster than EF

2. The class library supports all kinds of parsing functions at the product level

3. As long as you reference a DLL of SqlSugar, you can use it to parse various databases, support Sql functions, and support common native functions

 

install

.NET CORE / NET5   Nuget SqlSugarCore

.NET 4.5   Nuget SqlSugar 

.NET 4.0 Nuget SqlSuagr 4.x

 

introduction

Let's start with an example:

static void Main(string[] args)
{
 var age = 11;
 Expression<Func<Test, bool>> exp = a => a.id == age; //expression
 SqlServerExpressionContext expContext = new SqlServerExpressionContext();//Create resolution object
 expContext.Resolve(exp, ResolveExpressType.WhereSingle);//Start parsing
 var value = expContext.Result.GetString();//( [id] = @id0 )
 var pars = expContext.Parameters;// @id:11
}  

Here are the debugging results:

 

Through the above example, we can perfectly convert the expression into Sql statement

 

Tutorial case

1. How to create an ExpressionContext parsing object

We can use sqlsugar Dbtype distinguishes the database and instantiates it

ExpressionContext expContext=null;
switch (dbtype)
{
case DbType.MySql:
expContext = new MySqlExpressionContext();
break;
case DbType.SqlServer:
expContext = new SqlServerExpressionContext();
break;
case DbType.Sqlite:
expContext = new SqliteExpressionContext();
break;
case DbType.Oracle:
expContext = new OracleExpressionContext();
break;
case DbType.PostgreSQL:
expContext = new PostgreSQLExpressionContext();
break;
case DbType.Dm:
expContext = new DmExpressionContext();
break;
case DbType.Kdbndp:
expContext = new KdbndpExpressionContext();
break;
default:
throw new Exception("I won't support it");

 

2. Analysis of Where condition

It is basically the same as writing EF, and the commonly used ones will be supported

Expression<Func<DataTestInfo2, bool>> exp = it => it.Bool2== b.Value;
expContext.Resolve(exp, ResolveExpressType.WhereSingle);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//( [Bool2] = @Bool20 )

We're writing an example of Like

Expression<Func<Student, bool>> exp = it => it.Name.Contains(schoolData.Name);
ExpressionContext expContext = new ExpressionContext();
expContext.Resolve(exp, ResolveExpressType.WhereMultiple);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//([it].[Name] like '%'+@MethodConst0+'%') 

bool type parsing is one of the difficulties in ORM parsing, and there are many situations

Expression<Func<DataTestInfo2, bool>> exp = it => it.Bool1&&it.Bool1;
SqlServerExpressionContext expContext = new SqlServerExpressionContext();
expContext.Resolve(exp, ResolveExpressType.WhereSingle);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//( ( [Bool1]=1 ) AND ( [Bool1]=1 ) )

Support for diversified bool interpretation

Expression<Func<Student, bool>> exp = it =>true&& it.Name != null;
ExpressionContext expContext = new ExpressionContext();
expContext.Resolve(exp, ResolveExpressType.WhereSingle);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//(( 1 = 1 ) AND( [Name] IS NOT NULL ))

Multi table query support. In multi table query, we need to add prefix. For example, we want it id instead of id

  Expression<Func<Student, bool>> exp = it => (it.Id > 1 && it.Name != name || it.Id == 1) || it.Name == WhereConst.name;
  ExpressionContext expContext = new ExpressionContext();
  expContext.Resolve(exp, ResolveExpressType.WhereMultiple);
  var value = expContext.Result.GetString();
  var pars = expContext.Parameters;
//(((( [it].[Id] > @Id0 ) AND ( [it].[Name] <> @Name1 )) OR ( [it].[Id] = @Id2 )) OR ( [it].[Name] = @Name3 ))

 

3. How to parse Select

Support entity class resolution, query single field resolution and anonymous object resolution

Expression<Func<DataTestInfo2, DataTestInfo2>> exp =it => new DataTestInfo2() {  Bool1=it.Bool1 , Bool2=it.Bool2 };
ExpressionContext expContext = new ExpressionContext();
expContext.IsSingle = false;
expContext.Resolve(exp, ResolveExpressType.SelectSingle);
var selectorValue = expContext.Result.GetString();
var pars = expContext.Parameters;
//[Bool1] AS [Bool1] , [Bool2] AS [Bool2] 

 

Expression<Func<Student, School, object>> exp = (it, school) => new { Name = "a", Id = it.Id / 2, SchoolId = school.Id };
ExpressionContext expContext = new ExpressionContext();
expContext.IsSingle = false;
expContext.Resolve(exp, ResolveExpressType.SelectMultiple);
var selectorValue = expContext.Result.GetString();
// @constant0 AS [Name] , ( [it].[Id] / @Id1 ) AS [Id] , [school].[Id] AS [SchoolId] 

 

3. Resolution of field names

For example, orderby (it = > it. Name) like this, we need to get the name

Expression<Func<Student, object>> exp = it => it.Name;
ExpressionContext expContext = GetContext();
expContext.Resolve(exp, ResolveExpressType.FieldSingle);
var selectorValue = expContext.Result.GetString();
//Name

Statistics single field

Expression<Func<Student, object>> exp = it =>SqlFunc.AggregateAvg(it.Id);
ExpressionContext expContext = GetContext();
expContext.Resolve(exp, ResolveExpressType.FieldMultiple);
var selectorValue = expContext.Result.GetString();
//AVG([it].[Id])

 

4. Sql function support

Expression<Func<Student, bool>> exp = it => (it.Name.Contains("a")? 1:2)==1;
SqlServerExpressionContext expContext = new SqlServerExpressionContext();
expContext.Resolve(exp, ResolveExpressType.WhereSingle);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;
//(( CASE  WHEN  ([Name] like '%'+@MethodConst0+'%')  THEN @MethodConst1  ELSE @MethodConst2 END ) = @Const3 )

Supported C# functions:

.ToString  .Contains  .Length

.ToLower  .ToUpper  .ToSubstring 

.Equals    .HasValue  .Replace

.EndsWith  .StartsWith  .Trim

.HasValue  .Value  .AddDay  .Date

And the commonly used convert Toint32 wait

 

SqlFunc. function

The SqlFunc function contains a large number of SQL functions

 SqlFunc.IF(st.Id > 1)
     .Return(st.Id)
     .ElseIF(st.Id == 1)
     .Return(st.SchoolId).End(st.Id) //Equal to Case when

 

5. Other functions

5.1 supporting features, such as our table name and entity name are different, we can also implement them

SqlServerExpressionContext expContext = new SqlServerExpressionContext();
expContext.MappingTables.Add(typeof(Student).Name,"OA_STUDENT")

Listing is also very easy

SqlServerExpressionContext expContext = new SqlServerExpressionContext();
expContext.MappingColumns.Add("Id","ID",typeof(Student).Name)

 

5.2 support sub query

Expression<Func<Test, bool>> exp = a => SqlFunc.Subqueryable<Sutdent>().Where(it => it.testId == a.id).Select(it => it.id) == 1);
var expContext = new SqlServerExpressionContext();
 expContext.Resolve(exp, ResolveExpressType.WhereSingle);
var value = expContext.Result.GetString();
var pars = expContext.Parameters;

 

6. Do it yourself

Through the above study, it should be quite easy for you to write the following syntax var oneclass = dB Queryable<Order, OrderItem, Custom>((o, i, c) => o.Id == i.OrderId&& o.CustomId == c.Id)) 

.Where(o=>o.id==1) 
.Where((o,i)=>i.xx==1) 
.OrderBy(o=>o.Id) .Select((o,i,c)=> new ViewOrder { Id=SqlFunc.GetSelfAndAutoFill(o.Id),// o.* CustomName=c.Name //[c].[Name] AS [CustomName] }).ToList()

The above functions are always shared with Where parsing, column parsing and Select parsing

1. The following three parses use Where

(o, i, c) => o.Id == i.OrderId&& o.CustomId == c.Id)
 vo=>o.id==1
(o,i)=>i.xx==1

2. The following one uses column parsing

o=>o.Id

3. The following one uses the analysis of Select

(o,i,c)=> new ViewOrder
 {
          Id=SqlFunc.GetSelfAndAutoFill(o.Id),// o.*
          CustomName=c.Name   //[c].[Name] AS [CustomName]
}

 

  

Source code download:

Your praise or your star is the driving force of open source developers. Open source is not easy to make money in harmony

https://github.com/sunkaixuan/SqlSugar     

 

Eggs:

In the next article, I will introduce how to use SqlSugar to develop code in WebFirst mode, leading the design and development concepts of CodeFirst and DbFirst, and also a summary of my more than ten years of development experience

Posted by k.soule on Tue, 03 May 2022 11:01:55 +0300