From a664bc41bc0bef1634b6153612fa21d9091b5c04 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Wed, 25 Dec 2019 18:27:45 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=AE=8C=E5=96=84=20ExpressionCall=20?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.DbContext/FreeSql.DbContext.xml | 7 - FreeSql.Tests/FreeSql.Tests/UnitTest2.cs | 1 + .../ExpressionCallAttribute.cs | 44 ++++- FreeSql/FreeSql.xml | 150 ++++++++++++++++++ FreeSql/Internal/CommonExpression.cs | 14 +- .../CommonProvider/AdoProvider/AdoProvider.cs | 10 +- .../AdoProvider/AdoProviderAsync.cs | 8 +- 7 files changed, 215 insertions(+), 19 deletions(-) diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index d9f91124..dc0203b8 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -110,13 +110,6 @@ 清空状态数据 - - - 根据 lambda 条件删除数据 - - - - 添加 diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs index 82594730..d97e28fc 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs @@ -13,6 +13,7 @@ using System.ComponentModel.DataAnnotations; using System.Threading; using System.Data.SqlClient; using kwlib; +using System.Text; namespace FreeSql.Tests { diff --git a/FreeSql/DataAnnotations/ExpressionCallAttribute.cs b/FreeSql/DataAnnotations/ExpressionCallAttribute.cs index 4342ff13..6970eca9 100644 --- a/FreeSql/DataAnnotations/ExpressionCallAttribute.cs +++ b/FreeSql/DataAnnotations/ExpressionCallAttribute.cs @@ -1,6 +1,9 @@ -using System; +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; using System.Collections.Generic; using System.Data.Common; +using System.Linq.Expressions; using System.Text; namespace FreeSql.DataAnnotations @@ -23,6 +26,15 @@ namespace FreeSql.DataAnnotations public class ExpressionCallContext { + internal ExpressionCallContext() + { + Utility = new DefaultUtility { _context = this }; + } + + public IUtility Utility { get; } + + internal CommonExpression _commonExp; + internal CommonExpression.ExpTSC _tsc; /// /// 数据库类型,可用于适配多种数据库环境 /// @@ -32,6 +44,10 @@ namespace FreeSql.DataAnnotations /// 已解析的表达式中参数内容 /// public Dictionary ParsedContent { get; } = new Dictionary(); + /// + /// 表达式原始值 + /// + public Dictionary RawExpression { get; } = new Dictionary(); /// /// 主对象的参数化对象,可重塑其属性 @@ -53,5 +69,31 @@ namespace FreeSql.DataAnnotations /// 返回表达式函数表示的 SQL 字符串 /// public string Result { get; set; } + + public interface IUtility + { + /// + /// 获取实体元数据 + /// + /// + /// + TableInfo GetTableByEntity(Type entityType); + + /// + /// 解析表达式 + /// + /// + /// + string ParseExpression(Expression exp); + } + + class DefaultUtility : IUtility + { + internal ExpressionCallContext _context; + + public TableInfo GetTableByEntity(Type entityType) => _context?._commonExp._common.GetTableByEntity(entityType); + + public string ParseExpression(Expression exp) => _context?._commonExp.ExpressionLambdaToSql(exp, _context._tsc.CloneDisableDiyParse()); + } } } diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index b6056f16..13ec6385 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -219,6 +219,11 @@ 已解析的表达式中参数内容 + + + 表达式原始值 + + 主对象的参数化对象,可重塑其属性 @@ -240,6 +245,20 @@ 返回表达式函数表示的 SQL 字符串 + + + 获取实体元数据 + + + + + + + 解析表达式 + + + + 索引名 @@ -2205,6 +2224,137 @@ + + + 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】 + + + + + + + + + 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 }) + + + + + + + 查询 + + + + + + + 查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 }) + + + + + + + + 查询 + + + + + + + 查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 }) + + + + + + + + 查询 + + + + + + + 查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 }) + + + + + + + + 在【主库】执行 + + + + + + + + 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 }) + + + + + + + + 在【主库】执行 + + + + + + + + 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 }) + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 }) + + + + + + + + + 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new { age = 25 }) + + + + + + 可自定义解析表达式 diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 1d68f397..a6beb913 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -602,15 +602,25 @@ namespace FreeSql.Internal exp3.Method.GetCustomAttributes(typeof(ExpressionCallAttribute), true).Any() )) { - var ecc = new ExpressionCallContext { DataType = _ado.DataType, UserParameters = tsc.dbParams == null ? null : new List(), FormatSql = obj => formatSql(obj, null, null, null) }; + var ecc = new ExpressionCallContext { + _commonExp = this, + _tsc = tsc, + DataType = _ado.DataType, + UserParameters = tsc.dbParams == null ? null : new List(), + FormatSql = obj => formatSql(obj, null, null, null) + }; var exp3MethodParams = exp3.Method.GetParameters(); var dbParamsIndex = tsc.dbParams?.Count; - ecc.ParsedContent.Add(exp3MethodParams[0].Name, exp3MethodParams[0].GetCustomAttributes(typeof(RawValueAttribute), true).Any() ? null: ExpressionLambdaToSql(exp3.Arguments[0], tsc)); + ecc.RawExpression.Add(exp3MethodParams[0].Name, exp3.Arguments[0]); + ecc.ParsedContent.Add(exp3MethodParams[0].Name, exp3MethodParams[0].GetCustomAttributes(typeof(RawValueAttribute), true).Any() ? null : ExpressionLambdaToSql(exp3.Arguments[0], tsc)); if (tsc.dbParams?.Count > dbParamsIndex) ecc.DbParameter = tsc.dbParams.Last(); List oldDbParams = tsc.SetDbParamsReturnOld(null); for (var a = 1; a < exp3.Arguments.Count; a++) if (exp3.Arguments[a].Type != typeof(ExpressionCallContext)) + { + ecc.RawExpression.Add(exp3MethodParams[a].Name, exp3.Arguments[a]); ecc.ParsedContent.Add(exp3MethodParams[a].Name, exp3MethodParams[a].GetCustomAttributes(typeof(RawValueAttribute), true).Any() ? null : ExpressionLambdaToSql(exp3.Arguments[a], tsc)); + } tsc.SetDbParamsReturnOld(oldDbParams); var exp3InvokeParams = new object[exp3.Arguments.Count]; diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs index 3c0e3054..11299db6 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs @@ -78,7 +78,7 @@ namespace FreeSql.Internal.CommonProvider cmd.Parameters.Clear(); if (isThrowException) { - cmd.Dispose(); + if (DataType == DataType.Sqlite) cmd.Dispose(); throw e; } } @@ -575,7 +575,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); ExecuteReaderMultiple(multipleResult, connection, transaction, readerHander, cmdType, cmdText, cmdParms); return; } @@ -638,7 +638,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); } public object[][] ExecuteArray(string cmdText, object parms = null) => ExecuteArray(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); public object[][] ExecuteArray(DbTransaction transaction, string cmdText, object parms = null) => ExecuteArray(null, transaction, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -739,7 +739,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); return val; } public object ExecuteScalar(string cmdText, object parms = null) => ExecuteScalar(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -775,7 +775,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); return val; } diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs index efe6cd71..694ac18c 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs @@ -504,7 +504,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); await ExecuteReaderMultipleAsync(multipleResult, connection, transaction, readerHander, cmdType, cmdText, cmdParms); return; } @@ -567,7 +567,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(pool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); } public Task ExecuteArrayAsync(string cmdText, object parms = null) => ExecuteArrayAsync(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); public Task ExecuteArrayAsync(DbTransaction transaction, string cmdText, object parms = null) => ExecuteArrayAsync(null, transaction, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -669,7 +669,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); return val; } public Task ExecuteScalarAsync(string cmdText, object parms = null) => ExecuteScalarAsync(null, null, CommandType.Text, cmdText, GetDbParamtersByObject(cmdText, parms)); @@ -705,7 +705,7 @@ namespace FreeSql.Internal.CommonProvider } LoggerException(this.MasterPool, pc, ex, dt, logtxt); pc.cmd.Parameters.Clear(); - pc.cmd.Dispose(); + if (DataType == DataType.Sqlite) pc.cmd.Dispose(); return val; }