From 7c42c6779750d69cfe1ca9d74c7b23eb79d1b948 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Sun, 17 Nov 2019 17:14:00 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20MapType=20=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E7=9A=84=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=20=E6=95=B0=E7=BB=84.Contains=20=E5=BE=97=E5=88=B0=E6=98=AF?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E4=B9=8B=E5=89=8D=E7=9A=84=E5=80=BC=20bug?= =?UTF-8?q?=EF=BC=9B=20-=20=E4=BF=AE=E5=A4=8D=20MapType=20=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=20=E4=B8=8E=20IncludeMany=20=E5=8F=98=E5=BC=82?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=9C=AA=E6=98=A0=E5=B0=84=E5=A4=84=E7=90=86?= =?UTF-8?q?=E7=9A=84=20bug=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Extensions/FreeSqlGlobalExtensions.cs | 2 + FreeSql/FreeSql.xml | 131 ++++++++++++++++++ FreeSql/Internal/CommonExpression.cs | 23 ++- .../SelectProvider/Select1Provider.cs | 6 +- .../MySqlAdo/MySqlAdo.cs | 2 +- .../FreeSql.Provider.MySql/MySqlExpression.cs | 8 +- .../Default/OdbcAdo/OdbcAdo.cs | 2 +- .../Default/OdbcExpression.cs | 8 +- .../MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs | 2 +- .../MySql/OdbcMySqlExpression.cs | 8 +- .../Oracle/OdbcOracleAdo/OdbcOracleAdo.cs | 2 +- .../Oracle/OdbcOracleExpression.cs | 8 +- .../OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs | 2 +- .../PostgreSQL/OdbcPostgreSQLExpression.cs | 26 ++-- .../OdbcSqlServerAdo/OdbcSqlServerAdo.cs | 2 +- .../SqlServer/OdbcSqlServerExpression.cs | 8 +- .../OracleAdo/OracleAdo.cs | 2 +- .../OracleExpression.cs | 8 +- .../PostgreSQLAdo/PostgreSQLAdo.cs | 4 +- .../PostgreSQLExpression.cs | 29 ++-- .../SqlServerAdo/SqlServerAdo.cs | 2 +- .../SqlServerExpression.cs | 8 +- .../SqliteAdo/SqliteAdo.cs | 2 +- .../SqliteExpression.cs | 8 +- 24 files changed, 249 insertions(+), 54 deletions(-) diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index f6d27fac..340f6565 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -1,5 +1,6 @@ using FreeSql; using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; @@ -40,6 +41,7 @@ public static partial class FreeSqlGlobalExtensions public static bool IsNumberType(this Type that) => that == null ? false : dicIsNumberType.Value.ContainsKey(that); public static bool IsNullableType(this Type that) => that?.FullName.StartsWith("System.Nullable`1[") == true; public static bool IsAnonymousType(this Type that) => that?.FullName.StartsWith("<>f__AnonymousType") == true; + public static bool IsArrayOrList(this Type that) => that == null ? false : (that.IsArray || typeof(IList).IsAssignableFrom(that)); public static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GetGenericArguments().First() : that; internal static string NotNullAndConcat(this string that, params object[] args) => string.IsNullOrEmpty(that) ? null : string.Concat(new object[] { that }.Concat(args)); diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index e436e1d8..185896b3 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1996,6 +1996,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 11cf1b65..85720257 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -932,12 +932,12 @@ namespace FreeSql.Internal throw new ArgumentException($"{tb.DbName}.{memberExp.Member.Name} 被忽略,请检查 IsIgnore 设置,确认 get/set 为 public"); throw new ArgumentException($"{tb.DbName} 找不到列 {memberExp.Member.Name}"); } + var curcol = tb.ColumnsByCs[memberExp.Member.Name]; if (tsc._selectColumnMap != null) - { - tsc._selectColumnMap.Add(new SelectColumnInfo { Table = null, Column = tb.ColumnsByCs[memberExp.Member.Name] }); - } - var name = tb.ColumnsByCs[memberExp.Member.Name].Attribute.Name; + tsc._selectColumnMap.Add(new SelectColumnInfo { Table = null, Column = curcol }); + var name = curcol.Attribute.Name; if (tsc.isQuoteName) name = _common.QuoteSqlName(name); + tsc.mapTypeTmp = curcol.Attribute.MapType == curcol.CsType ? null : curcol.Attribute.MapType; if (string.IsNullOrEmpty(tsc.alias001)) return name; return $"{tsc.alias001}.{name}"; } @@ -1098,7 +1098,8 @@ namespace FreeSql.Internal tsc._selectColumnMap.Add(new SelectColumnInfo { Table = find2, Column = col2 }); return ""; } - name2 = tb2.ColumnsByCs[mp2.Member.Name].Attribute.Name; + name2 = col2.Attribute.Name; + tsc.mapTypeTmp = col2.Attribute.MapType == col2.CsType ? null : col2.Attribute.MapType; break; case ExpressionType.Call: break; } @@ -1150,10 +1151,22 @@ namespace FreeSql.Internal public bool isDisableDiyParse { get; set; } public ExpressionStyle style { get; set; } public Type mapType { get; set; } + public Type mapTypeTmp { get; set; } public TableInfo currentTable { get; set; } public List whereCascadeExpression { get; set; } public string alias001 { get; set; } //单表字段的表别名 + public void SetMapTypeTmp(Type newValue) + { + this.mapTypeTmp = null; + } + public Type SetMapTypeReturnOld(Type newValue) + { + var old = this.mapType; + this.mapType = newValue; + return old; + } + public ExpTSC CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(List v1, Func v2, SelectTableInfoType v3) { return new ExpTSC diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 96bee31f..a4e8d8f7 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -605,7 +605,7 @@ namespace FreeSql.Internal.CommonProvider for (var z = 0; z < tbref.Columns.Count; z++) { if (z > 0) sbWhereOne.Append(" AND "); - sbWhereOne.Append(_commonUtils.FormatSql($"{subSelectT1Alias}.{_commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)}={{0}}", getListValue(list[y], tbref.Columns[z].CsName, z))); + sbWhereOne.Append(_commonUtils.FormatSql($"{subSelectT1Alias}.{_commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)}={{0}}", Utils.GetDataReaderValue(tbref.RefColumns[z].Attribute.MapType, getListValue(list[y], tbref.Columns[z].CsName, z)))); } sbWhereOne.Append(")"); var whereOne = sbWhereOne.ToString(); @@ -797,7 +797,7 @@ namespace FreeSql.Internal.CommonProvider for (var z = 0; z < tbref.Columns.Count; z++) { if (z > 0) sbWhereOne.Append(" AND "); - sbWhereOne.Append(_commonUtils.FormatSql($" midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[z].Attribute.Name)}={{0}}", getListValue1(list[y], tbref.Columns[z].CsName))); + sbWhereOne.Append(_commonUtils.FormatSql($" midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[z].Attribute.Name)}={{0}}", Utils.GetDataReaderValue(tbref.MiddleColumns[z].Attribute.MapType, getListValue1(list[y], tbref.Columns[z].CsName)))); } sbWhereOne.Append(")"); var whereOne = sbWhereOne.ToString(); @@ -825,7 +825,7 @@ namespace FreeSql.Internal.CommonProvider subSelect._where.Clear(); if (tbref.Columns.Count == 1) { - subSelect.Where(_commonUtils.FormatSql($"midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[0].Attribute.Name)} in {{0}}", list.Select(a => getListValue1(a, tbref.Columns[0].CsName)).Distinct())); + subSelect.Where(_commonUtils.FormatSql($"midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[0].Attribute.Name)} in {{0}}", list.Select(a => Utils.GetDataReaderValue(tbref.MiddleColumns[0].Attribute.MapType, getListValue1(a, tbref.Columns[0].CsName))).Distinct())); } else { diff --git a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs index 3e0154ac..e061fe23 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlAdo/MySqlAdo.cs @@ -31,7 +31,7 @@ namespace FreeSql.MySql public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs index e91917f3..b795dbaf 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs @@ -99,14 +99,18 @@ namespace FreeSql.MySql argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break; diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs index a2fa7646..b42c5b48 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcAdo/OdbcAdo.cs @@ -32,7 +32,7 @@ namespace FreeSql.Odbc.Default public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs index 50262556..574455f7 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcExpression.cs @@ -106,14 +106,18 @@ namespace FreeSql.Odbc.Default argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break; diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs index b6ee5b3c..0cd07d54 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlAdo/OdbcMySqlAdo.cs @@ -31,7 +31,7 @@ namespace FreeSql.Odbc.MySql public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs index ca13a287..2bcd91b2 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs @@ -99,14 +99,18 @@ namespace FreeSql.Odbc.MySql argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break; diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs index b9b4d6f9..1bb9cfe0 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleAdo/OdbcOracleAdo.cs @@ -30,7 +30,7 @@ namespace FreeSql.Odbc.Oracle public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs index cd598adc..1c9f08e4 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs @@ -99,14 +99,18 @@ namespace FreeSql.Odbc.Oracle argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break; diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs index 3bef8669..0d7027a6 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLAdo/OdbcPostgreSQLAdo.cs @@ -32,7 +32,7 @@ namespace FreeSql.Odbc.PostgreSQL public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? "'t'" : "'f'"; diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs index 449c1a52..cc7839cb 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs @@ -103,11 +103,12 @@ namespace FreeSql.Odbc.PostgreSQL argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { - var left = objExp == null ? null : getExp(objExp); + string left = null; if (objType.FullName == typeof(Dictionary).FullName) { + left = objExp == null ? null : getExp(objExp); switch (callExp.Method.Name) { case "Contains": @@ -125,24 +126,30 @@ namespace FreeSql.Odbc.PostgreSQL switch (callExp.Method.Name) { case "Any": + left = objExp == null ? null : getExp(objExp); if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; return $"(case when {left} is null then 0 else array_length({left},1) end > 0)"; case "Contains": + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); //判断 in 或 array @> array - var right1 = getExp(callExp.Arguments[argIndex]); if (left.StartsWith("array[") || left.EndsWith("]")) - return $"{right1} in ({left.Substring(6, left.Length - 7)})"; + return $"{args1} in ({left.Substring(6, left.Length - 7)})"; if (left.StartsWith("(") || left.EndsWith(")")) - return $"{right1} in {left}"; - if (right1.StartsWith("(") || right1.EndsWith(")")) right1 = $"array[{right1.TrimStart('(').TrimEnd(')')}]"; - right1 = $"array[{right1}]"; + return $"{args1} in {left}"; + if (args1.StartsWith("(") || args1.EndsWith(")")) args1 = $"array[{args1.TrimStart('(').TrimEnd(')')}]"; + args1 = $"array[{args1}]"; if (objExp != null) { var dbinfo = _common._orm.CodeFirst.GetDbInfo(objExp.Type); - if (dbinfo.HasValue) right1 = $"{right1}::{dbinfo.Value.dbtype}"; + if (dbinfo.HasValue) args1 = $"{args1}::{dbinfo.Value.dbtype}"; } - return $"({left} @> {right1})"; + return $"({left} @> {args1})"; case "Concat": + left = objExp == null ? null : getExp(objExp); if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; var right2 = getExp(callExp.Arguments[argIndex]); if (right2.StartsWith("(") || right2.EndsWith(")")) right2 = $"array[{right2.TrimStart('(').TrimEnd(')')}]"; @@ -151,6 +158,7 @@ namespace FreeSql.Odbc.PostgreSQL case "GetLongLength": case "Length": case "Count": + left = objExp == null ? null : getExp(objExp); if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; return $"case when {left} is null then 0 else array_length({left},1) end"; } diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs index 360c7b47..3920f4b6 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerAdo/OdbcSqlServerAdo.cs @@ -30,7 +30,7 @@ namespace FreeSql.Odbc.SqlServer public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs index f96d7c83..74a752c9 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs @@ -103,14 +103,18 @@ namespace FreeSql.Odbc.SqlServer argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break; diff --git a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs index dc0c4790..8c45bb19 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleAdo/OracleAdo.cs @@ -30,7 +30,7 @@ namespace FreeSql.Oracle public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.Oracle/OracleExpression.cs b/Providers/FreeSql.Provider.Oracle/OracleExpression.cs index 80016c64..a5f35911 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleExpression.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleExpression.cs @@ -99,14 +99,18 @@ namespace FreeSql.Oracle argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break; diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs index 0c3b492e..eee3e5c9 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs @@ -33,9 +33,9 @@ namespace FreeSql.PostgreSQL public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList() || param is JToken || param is JObject || param is JArray)) param = Utils.GetDataReaderValue(mapType, param); - bool isdic = false; + bool isdic; if (param is bool || param is bool?) return (bool)param ? "'t'" : "'f'"; else if (param is string || param is char) diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs index 6c203306..4507cebe 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs @@ -104,14 +104,15 @@ namespace FreeSql.PostgreSQL argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { - var left = objExp == null ? null : getExp(objExp); + string left = null; switch (objType.FullName) { case "Newtonsoft.Json.Linq.JToken": case "Newtonsoft.Json.Linq.JObject": case "Newtonsoft.Json.Linq.JArray": + left = objExp == null ? null : getExp(objExp); switch (callExp.Method.Name) { case "Any": return $"(jsonb_array_length(coalesce({left},'[]')) > 0)"; @@ -137,6 +138,7 @@ namespace FreeSql.PostgreSQL } if (objType.FullName == typeof(Dictionary).FullName) { + left = objExp == null ? null : getExp(objExp); switch (callExp.Method.Name) { case "Contains": @@ -154,24 +156,30 @@ namespace FreeSql.PostgreSQL switch (callExp.Method.Name) { case "Any": + left = objExp == null ? null : getExp(objExp); if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; return $"(case when {left} is null then 0 else array_length({left},1) end > 0)"; case "Contains": + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); + left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); //判断 in 或 array @> array - var right1 = getExp(callExp.Arguments[argIndex]); if (left.StartsWith("array[") || left.EndsWith("]")) - return $"{right1} in ({left.Substring(6, left.Length - 7)})"; + return $"{args1} in ({left.Substring(6, left.Length - 7)})"; if (left.StartsWith("(") || left.EndsWith(")")) - return $"{right1} in {left}"; - if (right1.StartsWith("(") || right1.EndsWith(")")) right1 = $"array[{right1.TrimStart('(').TrimEnd(')')}]"; - right1 = $"array[{right1}]"; + return $"{args1} in {left}"; + if (args1.StartsWith("(") || args1.EndsWith(")")) args1 = $"array[{args1.TrimStart('(').TrimEnd(')')}]"; + args1 = $"array[{args1}]"; if (objExp != null) { var dbinfo = _common._orm.CodeFirst.GetDbInfo(objExp.Type); - if (dbinfo.HasValue) right1 = $"{right1}::{dbinfo.Value.dbtype}"; + if (dbinfo.HasValue) args1 = $"{args1}::{dbinfo.Value.dbtype}"; } - return $"({left} @> {right1})"; + return $"({left} @> {args1})"; case "Concat": + left = objExp == null ? null : getExp(objExp); if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; var right2 = getExp(callExp.Arguments[argIndex]); if (right2.StartsWith("(") || right2.EndsWith(")")) right2 = $"array[{right2.TrimStart('(').TrimEnd(')')}]"; @@ -180,6 +188,7 @@ namespace FreeSql.PostgreSQL case "GetLongLength": case "Length": case "Count": + left = objExp == null ? null : getExp(objExp); if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; return $"case when {left} is null then 0 else array_length({left},1) end"; } @@ -494,7 +503,7 @@ namespace FreeSql.PostgreSQL case "AddTicks": return $"(({left})::timestamp+(({args1})/10||' microseconds')::interval)"; case "AddYears": return $"(({left})::timestamp+(({args1})||' year')::interval)"; case "Subtract": - switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault() : exp.Arguments[0].Type).FullName) + switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GetGenericArguments().FirstOrDefault() : exp.Arguments[0].Type).FullName) { case "System.DateTime": return $"(extract(epoch from ({left})::timestamp-({args1})::timestamp)*1000000)"; case "System.TimeSpan": return $"(({left})::timestamp-(({args1})||' microseconds')::interval)"; diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs index adfc89be..c6799a13 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerAdo/SqlServerAdo.cs @@ -30,7 +30,7 @@ namespace FreeSql.SqlServer public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs index 4b0b0bb1..c775851f 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs @@ -103,14 +103,18 @@ namespace FreeSql.SqlServer argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break; diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs index d8df365d..9e27fc13 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteAdo/SqliteAdo.cs @@ -29,7 +29,7 @@ namespace FreeSql.Sqlite public override object AddslashesProcessParam(object param, Type mapType) { if (param == null) return "NULL"; - if (mapType != null && mapType != param.GetType()) + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false || mapType.IsArrayOrList())) param = Utils.GetDataReaderValue(mapType, param); if (param is bool || param is bool?) return (bool)param ? 1 : 0; diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs index 9f451e0b..ce13a196 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs @@ -99,14 +99,18 @@ namespace FreeSql.Sqlite argIndex++; } if (objType == null) objType = callExp.Method.DeclaringType; - if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) + if (objType != null || objType.IsArrayOrList()) { + tsc?.SetMapTypeTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc?.SetMapTypeReturnOld(tsc?.mapTypeTmp); var left = objExp == null ? null : getExp(objExp); + tsc.SetMapTypeReturnOld(oldMapType); switch (callExp.Method.Name) { case "Contains": //判断 in - return $"({getExp(callExp.Arguments[argIndex])}) in {left}"; + return $"({args1}) in {left}"; } } break;