From 43080a4052a1ee9ee2b26e9bdb83e109c25029e9 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Fri, 28 Dec 2018 18:25:26 +0800 Subject: [PATCH] =?UTF-8?q?SQL=E5=91=BD=E4=BB=A4=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=91=E8=A7=86=20+=20Pgsql=E8=A1=A8=E8=BE=BE=E5=BC=8F(Array?= =?UTF-8?q?/HStore/Jsonb)=E5=AE=9E=E7=8E=B0=E4=B8=8E=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PostgreSQL/PostgreSQLCodeFirstTest.cs | 3 + .../PostgreSQLExpression/OtherTest.cs | 249 ++++++++++++++++++ FreeSql.Tests/UnitTest1.cs | 13 +- FreeSql.Tests/g.cs | 8 + FreeSql/FreeSqlBuilder.cs | 23 +- FreeSql/Internal/CommonExpression.cs | 11 +- .../CommonProvider/AdoProvider/AdoProvider.cs | 14 +- .../AdoProvider/AdoProviderAsync.cs | 1 + .../SelectProvider/Select0Provider.cs | 19 +- .../SelectProvider/SelectGroupingProvider.cs | 6 +- FreeSql/MySql/MySqlExpression.cs | 4 + FreeSql/MySql/MySqlProvider.cs | 5 +- .../PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs | 20 +- FreeSql/PostgreSQL/PostgreSQLExpression.cs | 121 +++++++++ FreeSql/PostgreSQL/PostgreSQLProvider.cs | 5 +- FreeSql/SqlServer/SqlServerExpression.cs | 4 + FreeSql/SqlServer/SqlServerProvider.cs | 4 +- readme.md | 4 + 18 files changed, 479 insertions(+), 35 deletions(-) create mode 100644 FreeSql.Tests/PostgreSQL/PostgreSQLExpression/OtherTest.cs diff --git a/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs b/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs index ae93b593..ff6d8d11 100644 --- a/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs +++ b/FreeSql.Tests/PostgreSQL/PostgreSQLCodeFirstTest.cs @@ -58,6 +58,9 @@ namespace FreeSql.Tests.PostgreSQL { public void CurdAllField() { NpgsqlConnection.GlobalTypeMapper.UseLegacyPostgis(); + var sql1 = select.Where(a => a.testFieldIntArray.Contains(1)).ToSql(); + var sql2 = select.Where(a => a.testFieldIntArray.Contains(1)).ToSql(); + var item = new TableAllType { }; item.Id = (int)insert.AppendData(item).ExecuteIdentity(); diff --git a/FreeSql.Tests/PostgreSQL/PostgreSQLExpression/OtherTest.cs b/FreeSql.Tests/PostgreSQL/PostgreSQLExpression/OtherTest.cs new file mode 100644 index 00000000..91e392aa --- /dev/null +++ b/FreeSql.Tests/PostgreSQL/PostgreSQLExpression/OtherTest.cs @@ -0,0 +1,249 @@ +using FreeSql.DataAnnotations; +using Newtonsoft.Json.Linq; +using Npgsql; +using Npgsql.LegacyPostgis; +using NpgsqlTypes; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using Xunit; + +namespace FreeSql.Tests.PostgreSQLExpression { + public class OtherTest { + + ISelect select => g.pgsql.Select(); + + public OtherTest() { + NpgsqlConnection.GlobalTypeMapper.UseLegacyPostgis(); + } + + + [Fact] + public void Array() { + + var sql1 = select.Where(a => a.testFieldIntArray.Contains(1)).ToList(); + var sql2 = select.Where(a => a.testFieldIntArray.Contains(1) == false).ToList(); + + var sql3 = select.Where(a => a.testFieldIntArray.Any()).ToList(); + var sql4 = select.Where(a => a.testFieldIntArray.Any() == false).ToList(); + + var sql5 = select.ToList(a => a.testFieldIntArray.Concat(new[] { 1, 2, 3 })); + + var sql6 = select.Where(a => a.testFieldIntArray.GetLength(1) > 0).ToList(); + var sql7 = select.Where(a => a.testFieldIntArray.GetLongLength(1) > 0).ToList(); + var sql8 = select.Where(a => a.testFieldIntArray.Length > 0).ToList(); + var sql9 = select.Where(a => a.testFieldIntArray.Count() > 0).ToList(); + } + + [Fact] + public void Jsonb() { + + var sql1 = select.Where(a => a.testFieldJToken.Contains(JToken.Parse("{a:1}"))).ToList(); + var sql2 = select.Where(a => a.testFieldJToken.Contains(JToken.Parse("{a:1}")) == false).ToList(); + var sql111 = select.Where(a => a.testFieldJToken.Contains("{a:1}")).ToList(); + var sql222 = select.Where(a => a.testFieldJToken.Contains("{a:1}") == false).ToList(); + + var sql3 = select.Where(a => a.testFieldJObject.ContainsKey("a")).ToList(); + var sql4 = select.Where(a => a.testFieldJObject.ContainsKey("a") == false).ToList(); + + var sql5 = select.Where(a => a.testFieldJArray.Contains(JToken.Parse("{a:1}"))).ToList(); + var sql6 = select.Where(a => a.testFieldJArray.Contains(JToken.Parse("{a:1}")) == false).ToList(); + var sql555 = select.Where(a => a.testFieldJArray.Contains("{a:1}")).ToList(); + var sql666 = select.Where(a => a.testFieldJArray.Contains("{a:1}") == false).ToList(); + + //var sql7 = select.Where(a => a.testFieldJToken.Any()).ToList(); + //var sql8 = select.Where(a => a.testFieldJToken.Any() == false).ToList(); + + var sql9 = select.Where(a => a.testFieldJArray.Any()).ToList(); + var sql10 = select.Where(a => a.testFieldJArray.Any() == false).ToList(); + + //var sql11 = select.ToList(a => a.testFieldJToken.Concat(JToken.Parse("{a:1}"))); + //var sql12 = select.ToList(a => a.testFieldJObject.Concat(JToken.Parse("{a:1}"))); + //var sql13 = select.ToList(a => a.testFieldJArray.Concat(JToken.Parse("{a:1}"))); + + //var sql14 = select.Where(a => a.testFieldJToken.Count() > 0).ToList(); + //var sql15 = select.Where(a => a.testFieldJObject.Count > 0).ToList(); + var sql16 = select.Where(a => a.testFieldJArray.Count() > 0).ToList(); + var sql17 = select.Where(a => a.testFieldJArray.LongCount() > 0).ToList(); + var sql18 = select.Where(a => a.testFieldJArray.Count > 0).ToList(); + } + + [Fact] + public void HStore() { + + var sql1 = select.Where(a => a.testFieldHStore.ContainsKey("a")).ToList(); + var sql2 = select.Where(a => a.testFieldHStore.ContainsKey("a") == false).ToList(); + } + + [Table(Name = "tb_alltype")] + class TableAllType { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public bool testFieldBool { get; set; } + public sbyte testFieldSByte { get; set; } + public short testFieldShort { get; set; } + public int testFieldInt { get; set; } + public long testFieldLong { get; set; } + public byte testFieldByte { get; set; } + public ushort testFieldUShort { get; set; } + public uint testFieldUInt { get; set; } + public ulong testFieldULong { get; set; } + public double testFieldDouble { get; set; } + public float testFieldFloat { get; set; } + public decimal testFieldDecimal { get; set; } + public TimeSpan testFieldTimeSpan { get; set; } + public DateTime testFieldDateTime { get; set; } + public byte[] testFieldBytes { get; set; } + public string testFieldString { get; set; } + public Guid testFieldGuid { get; set; } + public NpgsqlPoint testFieldNpgsqlPoint { get; set; } + public NpgsqlLine testFieldNpgsqlLine { get; set; } + public NpgsqlLSeg testFieldNpgsqlLSeg { get; set; } + public NpgsqlBox testFieldNpgsqlBox { get; set; } + public NpgsqlPath testFieldNpgsqlPath { get; set; } + public NpgsqlPolygon testFieldNpgsqlPolygon { get; set; } + public NpgsqlCircle testFieldNpgsqlCircle { get; set; } + public (IPAddress Address, int Subnet) testFieldCidr { get; set; } + public NpgsqlRange testFieldInt4range { get; set; } + public NpgsqlRange testFieldInt8range { get; set; } + public NpgsqlRange testFieldNumrange { get; set; } + public NpgsqlRange testFieldTsrange { get; set; } + + public bool? testFieldBoolNullable { get; set; } + public sbyte? testFieldSByteNullable { get; set; } + public short? testFieldShortNullable { get; set; } + public int? testFieldIntNullable { get; set; } + public long? testFielLongNullable { get; set; } + public byte? testFieldByteNullable { get; set; } + public ushort? testFieldUShortNullable { get; set; } + public uint? testFieldUIntNullable { get; set; } + public ulong? testFieldULongNullable { get; set; } + public double? testFieldDoubleNullable { get; set; } + public float? testFieldFloatNullable { get; set; } + public decimal? testFieldDecimalNullable { get; set; } + public TimeSpan? testFieldTimeSpanNullable { get; set; } + public DateTime? testFieldDateTimeNullable { get; set; } + public Guid? testFieldGuidNullable { get; set; } + public NpgsqlPoint? testFieldNpgsqlPointNullable { get; set; } + public NpgsqlLine? testFieldNpgsqlLineNullable { get; set; } + public NpgsqlLSeg? testFieldNpgsqlLSegNullable { get; set; } + public NpgsqlBox? testFieldNpgsqlBoxNullable { get; set; } + public NpgsqlPath? testFieldNpgsqlPathNullable { get; set; } + public NpgsqlPolygon? testFieldNpgsqlPolygonNullable { get; set; } + public NpgsqlCircle? testFieldNpgsqlCircleNullable { get; set; } + public (IPAddress Address, int Subnet)? testFieldCidrNullable { get; set; } + public NpgsqlRange? testFieldInt4rangeNullable { get; set; } + public NpgsqlRange? testFieldInt8rangeNullable { get; set; } + public NpgsqlRange? testFieldNumrangeNullable { get; set; } + public NpgsqlRange? testFieldTsrangeNullable { get; set; } + + public BitArray testFieldBitArray { get; set; } + public IPAddress testFieldInet { get; set; } + public PhysicalAddress testFieldMacaddr { get; set; } + public JToken testFieldJToken { get; set; } + public JObject testFieldJObject { get; set; } + public JArray testFieldJArray { get; set; } + public Dictionary testFieldHStore { get; set; } + public PostgisPoint testFieldPostgisPoint { get; set; } + public PostgisLineString testFieldPostgisLineString { get; set; } + public PostgisPolygon testFieldPostgisPolygon { get; set; } + public PostgisMultiPoint testFieldPostgisMultiPoint { get; set; } + public PostgisMultiLineString testFieldPostgisPostgisMultiLineString { get; set; } + public PostgisMultiPolygon testFieldPostgisPostgisMultiPolygon { get; set; } + public PostgisGeometry testFieldPostgisGeometry { get; set; } + public PostgisGeometryCollection testFieldPostgisGeometryCollection { get; set; } + + public TableAllTypeEnumType1 testFieldEnum1 { get; set; } + public TableAllTypeEnumType1? testFieldEnum1Nullable { get; set; } + public TableAllTypeEnumType2 testFieldEnum2 { get; set; } + public TableAllTypeEnumType2? testFieldEnum2Nullable { get; set; } + + /* array */ + public bool[] testFieldBoolArray { get; set; } + public sbyte[] testFieldSByteArray { get; set; } + public short[] testFieldShortArray { get; set; } + public int[] testFieldIntArray { get; set; } + public long[] testFieldLongArray { get; set; } + public byte[] testFieldByteArray { get; set; } + public ushort[] testFieldUShortArray { get; set; } + public uint[] testFieldUIntArray { get; set; } + public ulong[] testFieldULongArray { get; set; } + public double[] testFieldDoubleArray { get; set; } + public float[] testFieldFloatArray { get; set; } + public decimal[] testFieldDecimalArray { get; set; } + public TimeSpan[] testFieldTimeSpanArray { get; set; } + public DateTime[] testFieldDateTimeArray { get; set; } + public byte[][] testFieldBytesArray { get; set; } + public string[] testFieldStringArray { get; set; } + public Guid[] testFieldGuidArray { get; set; } + public NpgsqlPoint[] testFieldNpgsqlPointArray { get; set; } + public NpgsqlLine[] testFieldNpgsqlLineArray { get; set; } + public NpgsqlLSeg[] testFieldNpgsqlLSegArray { get; set; } + public NpgsqlBox[] testFieldNpgsqlBoxArray { get; set; } + public NpgsqlPath[] testFieldNpgsqlPathArray { get; set; } + public NpgsqlPolygon[] testFieldNpgsqlPolygonArray { get; set; } + public NpgsqlCircle[] testFieldNpgsqlCircleArray { get; set; } + public (IPAddress Address, int Subnet)[] testFieldCidrArray { get; set; } + public NpgsqlRange[] testFieldInt4rangeArray { get; set; } + public NpgsqlRange[] testFieldInt8rangeArray { get; set; } + public NpgsqlRange[] testFieldNumrangeArray { get; set; } + public NpgsqlRange[] testFieldTsrangeArray { get; set; } + + public bool?[] testFieldBoolArrayNullable { get; set; } + public sbyte?[] testFieldSByteArrayNullable { get; set; } + public short?[] testFieldShortArrayNullable { get; set; } + public int?[] testFieldIntArrayNullable { get; set; } + public long?[] testFielLongArrayNullable { get; set; } + public byte?[] testFieldByteArrayNullable { get; set; } + public ushort?[] testFieldUShortArrayNullable { get; set; } + public uint?[] testFieldUIntArrayNullable { get; set; } + public ulong?[] testFieldULongArrayNullable { get; set; } + public double?[] testFieldDoubleArrayNullable { get; set; } + public float?[] testFieldFloatArrayNullable { get; set; } + public decimal?[] testFieldDecimalArrayNullable { get; set; } + public TimeSpan?[] testFieldTimeSpanArrayNullable { get; set; } + public DateTime?[] testFieldDateTimeArrayNullable { get; set; } + public Guid?[] testFieldGuidArrayNullable { get; set; } + public NpgsqlPoint?[] testFieldNpgsqlPointArrayNullable { get; set; } + public NpgsqlLine?[] testFieldNpgsqlLineArrayNullable { get; set; } + public NpgsqlLSeg?[] testFieldNpgsqlLSegArrayNullable { get; set; } + public NpgsqlBox?[] testFieldNpgsqlBoxArrayNullable { get; set; } + public NpgsqlPath?[] testFieldNpgsqlPathArrayNullable { get; set; } + public NpgsqlPolygon?[] testFieldNpgsqlPolygonArrayNullable { get; set; } + public NpgsqlCircle?[] testFieldNpgsqlCircleArrayNullable { get; set; } + public (IPAddress Address, int Subnet)?[] testFieldCidrArrayNullable { get; set; } + public NpgsqlRange?[] testFieldInt4rangeArrayNullable { get; set; } + public NpgsqlRange?[] testFieldInt8rangeArrayNullable { get; set; } + public NpgsqlRange?[] testFieldNumrangeArrayNullable { get; set; } + public NpgsqlRange?[] testFieldTsrangeArrayNullable { get; set; } + + public BitArray[] testFieldBitArrayArray { get; set; } + public IPAddress[] testFieldInetArray { get; set; } + public PhysicalAddress[] testFieldMacaddrArray { get; set; } + public JToken[] testFieldJTokenArray { get; set; } + public JObject[] testFieldJObjectArray { get; set; } + public JArray[] testFieldJArrayArray { get; set; } + public Dictionary[] testFieldHStoreArray { get; set; } + public PostgisPoint[] testFieldPostgisPointArray { get; set; } + public PostgisLineString[] testFieldPostgisLineStringArray { get; set; } + public PostgisPolygon[] testFieldPostgisPolygonArray { get; set; } + public PostgisMultiPoint[] testFieldPostgisMultiPointArray { get; set; } + public PostgisMultiLineString[] testFieldPostgisPostgisMultiLineStringArray { get; set; } + public PostgisMultiPolygon[] testFieldPostgisPostgisMultiPolygonArray { get; set; } + public PostgisGeometry[] testFieldPostgisGeometryArray { get; set; } + public PostgisGeometryCollection[] testFieldPostgisGeometryCollectionArray { get; set; } + + public TableAllTypeEnumType1[] testFieldEnum1Array { get; set; } + public TableAllTypeEnumType1?[] testFieldEnum1ArrayNullable { get; set; } + public TableAllTypeEnumType2[] testFieldEnum2Array { get; set; } + public TableAllTypeEnumType2?[] testFieldEnum2ArrayNullable { get; set; } + } + + public enum TableAllTypeEnumType1 { e1, e2, e3, e5 } + [Flags] public enum TableAllTypeEnumType2 { f1, f2, f3 } + } +} diff --git a/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/UnitTest1.cs index 48ed03da..ddff1556 100644 --- a/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/UnitTest1.cs @@ -4,6 +4,9 @@ using System; using System.Collections.Generic; using Xunit; using System.Linq; +using Newtonsoft.Json.Linq; +using NpgsqlTypes; +using Npgsql.LegacyPostgis; namespace FreeSql.Tests { public class UnitTest1 { @@ -25,15 +28,11 @@ namespace FreeSql.Tests { .Having(a => a.Count() < 300 || a.Avg(a.Key.mod4) < 100) .OrderBy(a => a.Key.tt2) .OrderByDescending(a => a.Count()) - .ToSql(a => new { a.Key.tt2, cou1 = a.Count(), arg1 = a.Avg(a.Key.mod4), + .ToList(a => new { a.Key.tt2, cou1 = a.Count(), arg1 = a.Avg(a.Key.mod4), ccc2 = a.Key.tt2 ?? "now()", - ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") + //ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") }); - - - var sss = new[] { 1, 2, 3 }; - sss.Count(); - + var arrg = g.mysql.Select().ToAggregate(a => new { sum = a.Sum(a.Key.Id + 11.11), avg = a.Avg(a.Key.Id), count = a.Count(), max = a.Max(a.Key.Id), min = a.Min(a.Key.Id) }); var arrg222 = g.mysql.Select().ToAggregate(a => new { sum = a.Sum(a.Key.Id + 11.11), avg = a.Avg(a.Key.Id), count = a.Count(), max = a.Max(a.Key.Id), min = a.Min(a.Key.Id) }); diff --git a/FreeSql.Tests/g.cs b/FreeSql.Tests/g.cs index 50b4724f..d0ec4ff1 100644 --- a/FreeSql.Tests/g.cs +++ b/FreeSql.Tests/g.cs @@ -8,6 +8,14 @@ public class g { public static IFreeSql mysql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10") .UseAutoSyncStructure(true) + + .UseMonitorCommand( + cmd => { + Console.WriteLine(cmd.CommandText); + }, //监听SQL命令对象,在执行前 + (cmd, traceLog) => { + Console.WriteLine(traceLog); + }) //监听SQL命令对象,在执行后 .Build(); public static IFreeSql sqlserver = new FreeSql.FreeSqlBuilder() diff --git a/FreeSql/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index 24fd6abd..299d30e9 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.Data.Common; using System.Text; namespace FreeSql { @@ -13,6 +14,8 @@ namespace FreeSql { string[] _slaveConnectionString; bool _isAutoSyncStructure = false; bool _isSyncStructureToLower = false; + Action _aopCommandExecuting = null; + Action _aopCommandExecuted = null; /// /// 使用缓存,不指定默认使用内存 @@ -71,17 +74,31 @@ namespace FreeSql { _isSyncStructureToLower = value; return this; } + /// + /// 监视数据库命令对象 + /// + /// 执行前 + /// 执行后 + /// + public FreeSqlBuilder UseMonitorCommand(Action executing, Action executed = null) { + _aopCommandExecuting = executing; + _aopCommandExecuted = executed; + return this; + } public IFreeSql Build() { IFreeSql ret = null; switch(_dataType) { - case DataType.MySql: ret = new MySql.MySqlProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger); break; - case DataType.SqlServer: ret = new SqlServer.SqlServerProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger); break; - case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger); break; + case DataType.MySql: ret = new MySql.MySqlProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; + case DataType.SqlServer: ret = new SqlServer.SqlServerProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; + case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; } if (ret != null) { ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure; ret.CodeFirst.IsSyncStructureToLower = _isSyncStructureToLower; + var ado = ret.Ado as Internal.CommonProvider.AdoProvider; + ado.AopCommandExecuting += _aopCommandExecuting; + ado.AopCommandExecuted += _aopCommandExecuted; } return ret; } diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index d9442500..e7c24a54 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -222,6 +222,8 @@ namespace FreeSql.Internal { case "Min": return $"min({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})"; } } + var other3Exp = ExpressionLambdaToSqlOther(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp; throw new Exception($"未现实函数表达式 {exp3} 解析"); case ExpressionType.MemberAccess: var exp4 = exp as MemberExpression; @@ -234,6 +236,8 @@ namespace FreeSql.Internal { case "System.TimeSpan": extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); break; } if (string.IsNullOrEmpty(extRet) == false) return extRet; + var other4Exp = ExpressionLambdaToSqlOther(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (string.IsNullOrEmpty(other4Exp) == false) return other4Exp; var expStack = new Stack(); expStack.Push(exp); @@ -341,7 +345,11 @@ namespace FreeSql.Internal { return $"{alias2}.{name2}"; } var expBinary = exp as BinaryExpression; - if (expBinary == null) return ""; + if (expBinary == null) { + var other99Exp = ExpressionLambdaToSqlOther(exp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (string.IsNullOrEmpty(other99Exp) == false) return other99Exp; + return ""; + } if (expBinary.NodeType == ExpressionType.Coalesce) { return _common.IsNull( ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName), @@ -368,5 +376,6 @@ namespace FreeSql.Internal { internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName); internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName); internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName); + internal abstract string ExpressionLambdaToSqlOther(Expression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName); } } diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs index 880bcd5e..227547cc 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs @@ -12,6 +12,8 @@ namespace FreeSql.Internal.CommonProvider { protected abstract void ReturnConnection(ObjectPool pool, Object conn, Exception ex); protected abstract DbCommand CreateCommand(); protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj); + internal Action AopCommandExecuting = null; + internal Action AopCommandExecuted = null; public bool IsTracePerformance { get; set; } = string.Compare(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), "Development", true) == 0; @@ -32,10 +34,14 @@ namespace FreeSql.Internal.CommonProvider { if (IsTracePerformance) { TimeSpan ts = DateTime.Now.Subtract(dt); if (e == null && ts.TotalMilliseconds > 100) - _log.LogWarning($"{pool.Policy.Name}执行SQL语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n{logtxt}"); + _log.LogWarning(logtxt = $"{pool.Policy.Name}执行SQL语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n{logtxt}"); + } + + if (e == null) { + AopCommandExecuted?.Invoke(cmd, logtxt); + return; } - if (e == null) return; string log = $"{pool.Policy.Name}数据库出错(执行SQL)〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓\r\n{cmd.CommandText}\r\n"; foreach (DbParameter parm in cmd.Parameters) log += parm.ParameterName.PadRight(20, ' ') + " = " + ((parm.Value ?? DBNull.Value) == DBNull.Value ? "NULL" : parm.Value) + "\r\n"; @@ -44,6 +50,9 @@ namespace FreeSql.Internal.CommonProvider { _log.LogError(log); RollbackTransaction(); + + AopCommandExecuted?.Invoke(cmd, log); + cmd.Parameters.Clear(); if (isThrowException) throw e; } @@ -261,6 +270,7 @@ namespace FreeSql.Internal.CommonProvider { AutoCommitTransaction(); if (IsTracePerformance) logtxt += $" AutoCommitTransaction: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n"; + AopCommandExecuting?.Invoke(cmd); return (tran, cmd); } } diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs index 789b81c6..2cf1c1d0 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs @@ -209,6 +209,7 @@ namespace FreeSql.Internal.CommonProvider { if (IsTracePerformance) logtxt += $" PrepareCommand_tran==null: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms cmdParms: {cmd.Parameters.Count}\r\n"; + AopCommandExecuting?.Invoke(cmd); return cmd; } } diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 0c609f96..da35408d 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -210,13 +210,13 @@ namespace FreeSql.Internal.CommonProvider { } return ret; } - protected (ReadAnonymousTypeInfo map, string field) GetNewExpressionField(NewExpression newexp) { + protected (ReadAnonymousTypeInfo map, string field) GetExpressionField(Expression newexp) { var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; _commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, null); - return (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null); + return (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null); } protected (ReadAnonymousTypeInfo map, string field) GetAllField() { var type = typeof(T1); @@ -281,7 +281,7 @@ namespace FreeSql.Internal.CommonProvider { var index = -10000; //临时规则,不返回 as1 _commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null); - this.GroupBy(map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null); + this.GroupBy(field.Length > 0 ? field.Remove(0, 2).ToString() : null); return new SelectGroupingProvider(this, map, _commonExpression); } protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType) { @@ -298,9 +298,12 @@ namespace FreeSql.Internal.CommonProvider { protected TSelect InternalOrderBy(Expression column) => this.OrderBy(_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)); protected TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC"); - protected List InternalToList(Expression select) => this.ToListMapReader(this.GetNewExpressionField(select as NewExpression)); - protected Task> InternalToListAsync(Expression select) => this.ToListMapReaderAsync(this.GetNewExpressionField(select as NewExpression)); - protected string InternalToSql(Expression select) => this.ToSql(this.GetNewExpressionField(select as NewExpression).field); + protected List InternalToList(Expression select) => this.ToListMapReader(this.GetExpressionField(select)); + protected Task> InternalToListAsync(Expression select) => this.ToListMapReaderAsync(this.GetExpressionField(select)); + protected string InternalToSql(Expression select) { + var af = this.GetExpressionField(select); + return this.ToSql(af.field); + } protected TReturn InternalToAggregate(Expression select) { var map = new ReadAnonymousTypeInfo(); @@ -308,7 +311,7 @@ namespace FreeSql.Internal.CommonProvider { var index = 0; _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null); - return this.ToListMapReader((map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault(); + return this.ToListMapReader((map, field.Length > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault(); } async protected Task InternalToAggregateAsync(Expression select) { var map = new ReadAnonymousTypeInfo(); @@ -316,7 +319,7 @@ namespace FreeSql.Internal.CommonProvider { var index = 0; _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null); - return (await this.ToListMapReaderAsync((map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null))).FirstOrDefault(); + return (await this.ToListMapReaderAsync((map, field.Length > 0 ? field.Remove(0, 2).ToString() : null))).FirstOrDefault(); } protected TSelect InternalWhere(Expression exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp, null)); diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs index 67c9f268..a205f595 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs @@ -57,7 +57,7 @@ namespace FreeSql.Internal.CommonProvider { _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString); var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TReturn)); - return method.Invoke(_select, new object[] { (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null) }) as List; + return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as List; } public Task> ToListAsync(Expression, TReturn>> select) { var map = new ReadAnonymousTypeInfo(); @@ -67,7 +67,7 @@ namespace FreeSql.Internal.CommonProvider { _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString); var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TReturn)); - return method.Invoke(_select, new object[] { (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null) }) as Task>; + return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task>; } public string ToSql(Expression, TReturn>> select) { @@ -77,7 +77,7 @@ namespace FreeSql.Internal.CommonProvider { _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString); var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) }); - return method.Invoke(_select, new object[] { map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null }) as string; + return method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string; } diff --git a/FreeSql/MySql/MySqlExpression.cs b/FreeSql/MySql/MySqlExpression.cs index 66e40f5e..f26d57da0 100644 --- a/FreeSql/MySql/MySqlExpression.cs +++ b/FreeSql/MySql/MySqlExpression.cs @@ -10,6 +10,10 @@ namespace FreeSql.MySql { public MySqlExpression(CommonUtils common) : base(common) { } + internal override string ExpressionLambdaToSqlOther(Expression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { + return null; + } + internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { if (exp.Expression == null) { switch (exp.Member.Name) { diff --git a/FreeSql/MySql/MySqlProvider.cs b/FreeSql/MySql/MySqlProvider.cs index 50a942eb..0fcd92b4 100644 --- a/FreeSql/MySql/MySqlProvider.cs +++ b/FreeSql/MySql/MySqlProvider.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.Data.Common; namespace FreeSql.MySql { @@ -25,8 +26,7 @@ namespace FreeSql.MySql { public ICache Cache { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public MySqlProvider(IDistributedCache cache, IConfiguration cacheStrategy, string masterConnectionString, string[] slaveConnectionString, ILogger log) { - CacheStrategy = cacheStrategy; + public MySqlProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) { if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.MySql"); this.InternalCommonUtils = new MySqlUtils(this); @@ -41,7 +41,6 @@ namespace FreeSql.MySql { internal CommonUtils InternalCommonUtils { get; } internal CommonExpression InternalCommonExpression { get; } - internal IConfiguration CacheStrategy { get; private set; } public void Transaction(Action handler) => Ado.Transaction(handler); diff --git a/FreeSql/PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs b/FreeSql/PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs index 979ab059..96b0dfe8 100644 --- a/FreeSql/PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs +++ b/FreeSql/PostgreSQL/PostgreSQLAdo/PostgreSQLAdo.cs @@ -1,9 +1,11 @@ using FreeSql.Internal; using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Linq; using Npgsql; using SafeObjectPool; using System; using System.Collections; +using System.Collections.Generic; using System.Data.Common; using System.Text; using System.Threading; @@ -25,6 +27,7 @@ namespace FreeSql.PostgreSQL { } static DateTime dt1970 = new DateTime(1970, 1, 1); public override object AddslashesProcessParam(object param) { + bool isdic = false; if (param == null) return "NULL"; if (param is bool || param is bool?) return (bool)param ? "'t'" : "'f'"; @@ -40,12 +43,25 @@ namespace FreeSql.PostgreSQL { return ((TimeSpan)param).Ticks / 10; else if (param is TimeSpan?) return (param as TimeSpan?).Value.Ticks / 10; - else if (param is IEnumerable) { + else if (param is JToken || param is JObject || param is JArray) + return string.Concat("'", param.ToString().Replace("'", "''"), "'::jsonb"); + else if ((isdic = param is Dictionary) || + param is IEnumerable>) { + var pgdics = isdic ? param as Dictionary : + param as IEnumerable>; + if (pgdics == null) return string.Concat("''::hstore"); + var pghstore = new StringBuilder(); + pghstore.Append("'"); + foreach (var dic in pgdics) + pghstore.Append("\"").Append(dic.Key.Replace("'", "''")).Append("\"=>") + .Append(dic.Key.Replace("'", "''")).Append(","); + return pghstore.Append("'::hstore"); + } else if (param is IEnumerable) { var sb = new StringBuilder(); var ie = param as IEnumerable; foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z)); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); - } else { + }else { return string.Concat("'", param.ToString().Replace("'", "''"), "'"); //if (param is string) return string.Concat('N', nparms[a]); } diff --git a/FreeSql/PostgreSQL/PostgreSQLExpression.cs b/FreeSql/PostgreSQL/PostgreSQLExpression.cs index e874898b..ad11884c 100644 --- a/FreeSql/PostgreSQL/PostgreSQLExpression.cs +++ b/FreeSql/PostgreSQL/PostgreSQLExpression.cs @@ -1,15 +1,136 @@ using FreeSql.Internal; using FreeSql.Internal.Model; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Text; namespace FreeSql.PostgreSQL { class PostgreSQLExpression : CommonExpression { public PostgreSQLExpression(CommonUtils common) : base(common) { } + internal override string ExpressionLambdaToSqlOther(Expression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { + switch (exp.NodeType) { + case ExpressionType.ArrayLength: + var arrOperExp = ExpressionLambdaToSql((exp as UnaryExpression).Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (arrOperExp.StartsWith("(") || arrOperExp.EndsWith(")")) return $"array_length(array[{arrOperExp.TrimStart('(').TrimEnd(')')}])"; + return $"case when {arrOperExp} is null then 0 else array_length({arrOperExp},1) end"; + case ExpressionType.Call: + var callExp = exp as MethodCallExpression; + var objExp = callExp.Object; + var objType = objExp?.Type; + if (objType?.FullName == "System.Byte[]") return null; + + var argIndex = 0; + if (objType == null && callExp.Method.DeclaringType.FullName == typeof(Enumerable).FullName) { + objExp = callExp.Arguments.FirstOrDefault(); + objType = objExp?.Type; + argIndex++; + } + if (objType == null) objType = callExp.Method.DeclaringType; + if (objType != null) { + var left = objExp == null ? null : ExpressionLambdaToSql(objExp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (objType.IsArray == true) { + if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; + switch (callExp.Method.Name) { + case "Any": return $"(case when {left} is null then 0 else array_length({left},1) end > 0)"; + case "Contains": return $"({left} @> array[{ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)}])"; + case "Concat": + var right2 = ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (right2.StartsWith("(") || right2.EndsWith(")")) right2 = $"array[{right2.TrimStart('(').TrimEnd(')')}]"; + return $"({left} || {right2})"; + case "GetLength": + case "GetLongLength": + case "Length": + case "Count": return $"case when {left} is null then 0 else array_length({left},1) end"; + } + } + switch (objType.FullName) { + case "Newtonsoft.Json.Linq.JToken": + case "Newtonsoft.Json.Linq.JObject": + case "Newtonsoft.Json.Linq.JArray": + switch (callExp.Method.Name) { + case "Any": return $"(jsonb_array_length(coalesce({left},'[]')) > 0)"; + case "Contains": + var json = ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (json.StartsWith("'") && json.EndsWith("'")) return $"(coalesce({left},'{{}}') @> {_common.FormatSql("{0}", JToken.Parse(json.Trim('\'')))})"; + return $"(coalesce({left},'{{}}') @> ({json})::jsonb)"; + case "ContainsKey": return $"(coalesce({left},'{{}}') ? {ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})"; + case "Concat": + var right2 = ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + return $"(coalesce({left},'{{}}') || {right2})"; + case "LongCount": + case "Count": return $"jsonb_array_length(coalesce({left},'[]'))"; + case "Parse": + var json2 = ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (json2.StartsWith("'") && json2.EndsWith("'")) return _common.FormatSql("{0}", JToken.Parse(json2.Trim('\''))); + return $"({json2})::jsonb"; + } + break; + } + if (objType.FullName == typeof(Dictionary).FullName) { + switch (callExp.Method.Name) { + case "Contains": + var right = ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + return $"({left} @> ({right}))"; + case "ContainsKey": return $"({left} ? {ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})"; + case "Concat": return $"({left} || {ExpressionLambdaToSql(callExp.Arguments[argIndex], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})"; + case "GetLength": + case "GetLongLength": + case "Count": return $"case when {left} is null then 0 else array_length(akeys({left}),1) end"; + case "Keys": return $"akeys({left})"; + case "Values": return $"avals({left})"; + } + } + } + break; + case ExpressionType.MemberAccess: + var memExp = exp as MemberExpression; + var memParentExp = memExp.Expression?.Type; + if (memParentExp?.FullName == "System.Byte[]") return null; + if (memParentExp != null) { + var left = ExpressionLambdaToSql(memExp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); + if (memParentExp.IsArray == true) { + if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]"; + switch (memExp.Member.Name) { + case "Length": + case "Count": return $"case when {left} is null then 0 else array_length({left},1) end"; + } + } + switch (memParentExp.FullName) { + case "Newtonsoft.Json.Linq.JToken": + case "Newtonsoft.Json.Linq.JObject": + case "Newtonsoft.Json.Linq.JArray": + switch (memExp.Member.Name) { + case "Count": return $"jsonb_array_length(coalesce({left},'[]'))"; + } + break; + } + if (memParentExp.FullName == typeof(Dictionary).FullName) { + switch (memExp.Member.Name) { + case "Count": return $"case when {left} is null then 0 else array_length(akeys({left}),1) end"; + case "Keys": return $"akeys({left})"; + case "Values": return $"avals({left})"; + } + } + } + break; + case ExpressionType.NewArrayInit: + var arrExp = exp as NewArrayExpression; + var arrSb = new StringBuilder(); + arrSb.Append("array["); + for (var a = 0; a < arrExp.Expressions.Count; a++) { + if (a > 0) arrSb.Append(","); + arrSb.Append(ExpressionLambdaToSql(arrExp.Expressions[a], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)); + } + return arrSb.Append("]").ToString(); + } + return null; + } + internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { if (exp.Expression == null) { switch (exp.Member.Name) { diff --git a/FreeSql/PostgreSQL/PostgreSQLProvider.cs b/FreeSql/PostgreSQL/PostgreSQLProvider.cs index d98fbfd5..5da914ea 100644 --- a/FreeSql/PostgreSQL/PostgreSQLProvider.cs +++ b/FreeSql/PostgreSQL/PostgreSQLProvider.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.Data.Common; namespace FreeSql.PostgreSQL { @@ -25,8 +26,7 @@ namespace FreeSql.PostgreSQL { public ICache Cache { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public PostgreSQLProvider(IDistributedCache cache, IConfiguration cacheStrategy, string masterConnectionString, string[] slaveConnectionString, ILogger log) { - CacheStrategy = cacheStrategy; + public PostgreSQLProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) { if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.PostgreSQL"); this.InternalCommonUtils = new PostgreSQLUtils(this); @@ -41,7 +41,6 @@ namespace FreeSql.PostgreSQL { internal CommonUtils InternalCommonUtils { get; } internal CommonExpression InternalCommonExpression { get; } - internal IConfiguration CacheStrategy { get; private set; } public void Transaction(Action handler) => Ado.Transaction(handler); diff --git a/FreeSql/SqlServer/SqlServerExpression.cs b/FreeSql/SqlServer/SqlServerExpression.cs index 48ad6683..d864afda 100644 --- a/FreeSql/SqlServer/SqlServerExpression.cs +++ b/FreeSql/SqlServer/SqlServerExpression.cs @@ -10,6 +10,10 @@ namespace FreeSql.SqlServer { public SqlServerExpression(CommonUtils common) : base(common) { } + internal override string ExpressionLambdaToSqlOther(Expression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { + return null; + } + internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List _tables, List _selectColumnMap, Func getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { if (exp.Expression == null) { switch (exp.Member.Name) { diff --git a/FreeSql/SqlServer/SqlServerProvider.cs b/FreeSql/SqlServer/SqlServerProvider.cs index 807c116e..f74a2fdc 100644 --- a/FreeSql/SqlServer/SqlServerProvider.cs +++ b/FreeSql/SqlServer/SqlServerProvider.cs @@ -25,8 +25,7 @@ namespace FreeSql.SqlServer { public ICache Cache { get; } public ICodeFirst CodeFirst { get; } public IDbFirst DbFirst { get; } - public SqlServerProvider(IDistributedCache cache, IConfiguration cacheStrategy, string masterConnectionString, string[] slaveConnectionString, ILogger log) { - CacheStrategy = cacheStrategy; + public SqlServerProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) { if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.SqlServer"); this.InternalCommonUtils = new SqlServerUtils(this); @@ -41,7 +40,6 @@ namespace FreeSql.SqlServer { internal CommonUtils InternalCommonUtils { get; } internal CommonExpression InternalCommonExpression { get; } - internal IConfiguration CacheStrategy { get; private set; } public void Transaction(Action handler) => Ado.Transaction(handler); diff --git a/readme.md b/readme.md index d380a217..05631257 100644 --- a/readme.md +++ b/readme.md @@ -23,6 +23,10 @@ IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, connstr) .UseSlave("connectionString1", "connectionString2") //使用从数据库,支持多个 + .UseMonitorCommand( + cmd => Console.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 + (cmd, traceLog) => Console.WriteLine(traceLog)) //监听SQL命令对象,在执行后 + .UseLogger(null) //使用日志,不指定默认输出控制台 ILogger .UseCache(null) //使用缓存,不指定默认使用内存 IDistributedCache