SQL命令执行监视 + Pgsql表达式(Array/HStore/Jsonb)实现与测试

This commit is contained in:
28810 2018-12-28 18:25:26 +08:00
parent 3ed1213865
commit 43080a4052
18 changed files with 479 additions and 35 deletions

View File

@ -58,6 +58,9 @@ namespace FreeSql.Tests.PostgreSQL {
public void CurdAllField() { public void CurdAllField() {
NpgsqlConnection.GlobalTypeMapper.UseLegacyPostgis(); 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 { }; var item = new TableAllType { };
item.Id = (int)insert.AppendData(item).ExecuteIdentity(); item.Id = (int)insert.AppendData(item).ExecuteIdentity();

View File

@ -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<TableAllType> select => g.pgsql.Select<TableAllType>();
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<int> testFieldInt4range { get; set; }
public NpgsqlRange<long> testFieldInt8range { get; set; }
public NpgsqlRange<decimal> testFieldNumrange { get; set; }
public NpgsqlRange<DateTime> 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<int>? testFieldInt4rangeNullable { get; set; }
public NpgsqlRange<long>? testFieldInt8rangeNullable { get; set; }
public NpgsqlRange<decimal>? testFieldNumrangeNullable { get; set; }
public NpgsqlRange<DateTime>? 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<string, string> 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<int>[] testFieldInt4rangeArray { get; set; }
public NpgsqlRange<long>[] testFieldInt8rangeArray { get; set; }
public NpgsqlRange<decimal>[] testFieldNumrangeArray { get; set; }
public NpgsqlRange<DateTime>[] 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<int>?[] testFieldInt4rangeArrayNullable { get; set; }
public NpgsqlRange<long>?[] testFieldInt8rangeArrayNullable { get; set; }
public NpgsqlRange<decimal>?[] testFieldNumrangeArrayNullable { get; set; }
public NpgsqlRange<DateTime>?[] 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<string, string>[] 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 }
}
}

View File

@ -4,6 +4,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Xunit; using Xunit;
using System.Linq; using System.Linq;
using Newtonsoft.Json.Linq;
using NpgsqlTypes;
using Npgsql.LegacyPostgis;
namespace FreeSql.Tests { namespace FreeSql.Tests {
public class UnitTest1 { public class UnitTest1 {
@ -25,15 +28,11 @@ namespace FreeSql.Tests {
.Having(a => a.Count() < 300 || a.Avg(a.Key.mod4) < 100) .Having(a => a.Count() < 300 || a.Avg(a.Key.mod4) < 100)
.OrderBy(a => a.Key.tt2) .OrderBy(a => a.Key.tt2)
.OrderByDescending(a => a.Count()) .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()", 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<TestInfo>().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 arrg = g.mysql.Select<TestInfo>().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<NullAggreTestTable>().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<NullAggreTestTable>().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) });

View File

@ -8,6 +8,14 @@ public class g {
public static IFreeSql mysql = new FreeSql.FreeSqlBuilder() 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") .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) .UseAutoSyncStructure(true)
.UseMonitorCommand(
cmd => {
Console.WriteLine(cmd.CommandText);
}, //监听SQL命令对象在执行前
(cmd, traceLog) => {
Console.WriteLine(traceLog);
}) //监听SQL命令对象在执行后
.Build(); .Build();
public static IFreeSql sqlserver = new FreeSql.FreeSqlBuilder() public static IFreeSql sqlserver = new FreeSql.FreeSqlBuilder()

View File

@ -2,6 +2,7 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Common;
using System.Text; using System.Text;
namespace FreeSql { namespace FreeSql {
@ -13,6 +14,8 @@ namespace FreeSql {
string[] _slaveConnectionString; string[] _slaveConnectionString;
bool _isAutoSyncStructure = false; bool _isAutoSyncStructure = false;
bool _isSyncStructureToLower = false; bool _isSyncStructureToLower = false;
Action<DbCommand> _aopCommandExecuting = null;
Action<DbCommand, string> _aopCommandExecuted = null;
/// <summary> /// <summary>
/// 使用缓存,不指定默认使用内存 /// 使用缓存,不指定默认使用内存
@ -71,17 +74,31 @@ namespace FreeSql {
_isSyncStructureToLower = value; _isSyncStructureToLower = value;
return this; return this;
} }
/// <summary>
/// 监视数据库命令对象
/// </summary>
/// <param name="executing">执行前</param>
/// <param name="executed">执行后</param>
/// <returns></returns>
public FreeSqlBuilder UseMonitorCommand(Action<DbCommand> executing, Action<DbCommand, string> executed = null) {
_aopCommandExecuting = executing;
_aopCommandExecuted = executed;
return this;
}
public IFreeSql Build() { public IFreeSql Build() {
IFreeSql ret = null; IFreeSql ret = null;
switch(_dataType) { switch(_dataType) {
case DataType.MySql: ret = new MySql.MySqlProvider(_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, null, _masterConnectionString, _slaveConnectionString, _logger); break; case DataType.SqlServer: ret = new SqlServer.SqlServerProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider(_cache, null, _masterConnectionString, _slaveConnectionString, _logger); break; case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
} }
if (ret != null) { if (ret != null) {
ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure; ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure;
ret.CodeFirst.IsSyncStructureToLower = _isSyncStructureToLower; ret.CodeFirst.IsSyncStructureToLower = _isSyncStructureToLower;
var ado = ret.Ado as Internal.CommonProvider.AdoProvider;
ado.AopCommandExecuting += _aopCommandExecuting;
ado.AopCommandExecuted += _aopCommandExecuted;
} }
return ret; return ret;
} }

View File

@ -222,6 +222,8 @@ namespace FreeSql.Internal {
case "Min": return $"min({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName)})"; 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} 解析"); throw new Exception($"未现实函数表达式 {exp3} 解析");
case ExpressionType.MemberAccess: case ExpressionType.MemberAccess:
var exp4 = exp as MemberExpression; var exp4 = exp as MemberExpression;
@ -234,6 +236,8 @@ namespace FreeSql.Internal {
case "System.TimeSpan": extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); break; case "System.TimeSpan": extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); break;
} }
if (string.IsNullOrEmpty(extRet) == false) return extRet; 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<Expression>(); var expStack = new Stack<Expression>();
expStack.Push(exp); expStack.Push(exp);
@ -341,7 +345,11 @@ namespace FreeSql.Internal {
return $"{alias2}.{name2}"; return $"{alias2}.{name2}";
} }
var expBinary = exp as BinaryExpression; 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) { if (expBinary.NodeType == ExpressionType.Coalesce) {
return _common.IsNull( return _common.IsNull(
ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName), ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName),
@ -368,5 +376,6 @@ namespace FreeSql.Internal {
internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName); internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName); internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName); internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName);
} }
} }

View File

@ -12,6 +12,8 @@ namespace FreeSql.Internal.CommonProvider {
protected abstract void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex); protected abstract void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex);
protected abstract DbCommand CreateCommand(); protected abstract DbCommand CreateCommand();
protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj); protected abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
internal Action<DbCommand> AopCommandExecuting = null;
internal Action<DbCommand, string> AopCommandExecuted = null;
public bool IsTracePerformance { get; set; } = string.Compare(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), "Development", true) == 0; public bool IsTracePerformance { get; set; } = string.Compare(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), "Development", true) == 0;
@ -32,10 +34,14 @@ namespace FreeSql.Internal.CommonProvider {
if (IsTracePerformance) { if (IsTracePerformance) {
TimeSpan ts = DateTime.Now.Subtract(dt); TimeSpan ts = DateTime.Now.Subtract(dt);
if (e == null && ts.TotalMilliseconds > 100) 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"; string log = $"{pool.Policy.Name}数据库出错执行SQL〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓\r\n{cmd.CommandText}\r\n";
foreach (DbParameter parm in cmd.Parameters) foreach (DbParameter parm in cmd.Parameters)
log += parm.ParameterName.PadRight(20, ' ') + " = " + ((parm.Value ?? DBNull.Value) == DBNull.Value ? "NULL" : parm.Value) + "\r\n"; 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); _log.LogError(log);
RollbackTransaction(); RollbackTransaction();
AopCommandExecuted?.Invoke(cmd, log);
cmd.Parameters.Clear(); cmd.Parameters.Clear();
if (isThrowException) throw e; if (isThrowException) throw e;
} }
@ -261,6 +270,7 @@ namespace FreeSql.Internal.CommonProvider {
AutoCommitTransaction(); AutoCommitTransaction();
if (IsTracePerformance) logtxt += $" AutoCommitTransaction: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n"; if (IsTracePerformance) logtxt += $" AutoCommitTransaction: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
AopCommandExecuting?.Invoke(cmd);
return (tran, cmd); return (tran, cmd);
} }
} }

View File

@ -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"; if (IsTracePerformance) logtxt += $" PrepareCommand_tran==null: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms cmdParms: {cmd.Parameters.Count}\r\n";
AopCommandExecuting?.Invoke(cmd);
return cmd; return cmd;
} }
} }

View File

@ -210,13 +210,13 @@ namespace FreeSql.Internal.CommonProvider {
} }
return ret; return ret;
} }
protected (ReadAnonymousTypeInfo map, string field) GetNewExpressionField(NewExpression newexp) { protected (ReadAnonymousTypeInfo map, string field) GetExpressionField(Expression newexp) {
var map = new ReadAnonymousTypeInfo(); var map = new ReadAnonymousTypeInfo();
var field = new StringBuilder(); var field = new StringBuilder();
var index = 0; var index = 0;
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, null); _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() { protected (ReadAnonymousTypeInfo map, string field) GetAllField() {
var type = typeof(T1); var type = typeof(T1);
@ -281,7 +281,7 @@ namespace FreeSql.Internal.CommonProvider {
var index = -10000; //临时规则,不返回 as1 var index = -10000; //临时规则,不返回 as1
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null); _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<TKey>(this, map, _commonExpression); return new SelectGroupingProvider<TKey>(this, map, _commonExpression);
} }
protected TSelect InternalJoin(Expression exp, SelectTableInfoType joinType) { 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 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 TSelect InternalOrderByDescending(Expression column) => this.OrderBy($"{_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, column, true, null)} DESC");
protected List<TReturn> InternalToList<TReturn>(Expression select) => this.ToListMapReader<TReturn>(this.GetNewExpressionField(select as NewExpression)); protected List<TReturn> InternalToList<TReturn>(Expression select) => this.ToListMapReader<TReturn>(this.GetExpressionField(select));
protected Task<List<TReturn>> InternalToListAsync<TReturn>(Expression select) => this.ToListMapReaderAsync<TReturn>(this.GetNewExpressionField(select as NewExpression)); protected Task<List<TReturn>> InternalToListAsync<TReturn>(Expression select) => this.ToListMapReaderAsync<TReturn>(this.GetExpressionField(select));
protected string InternalToSql<TReturn>(Expression select) => this.ToSql(this.GetNewExpressionField(select as NewExpression).field); protected string InternalToSql<TReturn>(Expression select) {
var af = this.GetExpressionField(select);
return this.ToSql(af.field);
}
protected TReturn InternalToAggregate<TReturn>(Expression select) { protected TReturn InternalToAggregate<TReturn>(Expression select) {
var map = new ReadAnonymousTypeInfo(); var map = new ReadAnonymousTypeInfo();
@ -308,7 +311,7 @@ namespace FreeSql.Internal.CommonProvider {
var index = 0; var index = 0;
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null); _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null);
return this.ToListMapReader<TReturn>((map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault(); return this.ToListMapReader<TReturn>((map, field.Length > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault();
} }
async protected Task<TReturn> InternalToAggregateAsync<TReturn>(Expression select) { async protected Task<TReturn> InternalToAggregateAsync<TReturn>(Expression select) {
var map = new ReadAnonymousTypeInfo(); var map = new ReadAnonymousTypeInfo();
@ -316,7 +319,7 @@ namespace FreeSql.Internal.CommonProvider {
var index = 0; var index = 0;
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null); _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null);
return (await this.ToListMapReaderAsync<TReturn>((map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null))).FirstOrDefault(); return (await this.ToListMapReaderAsync<TReturn>((map, field.Length > 0 ? field.Remove(0, 2).ToString() : null))).FirstOrDefault();
} }
protected TSelect InternalWhere(Expression exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp, null)); protected TSelect InternalWhere(Expression exp) => this.Where(_commonExpression.ExpressionWhereLambda(_tables, exp, null));

View File

@ -57,7 +57,7 @@ namespace FreeSql.Internal.CommonProvider {
_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString); _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString);
var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic);
method = method.MakeGenericMethod(typeof(TReturn)); method = method.MakeGenericMethod(typeof(TReturn));
return method.Invoke(_select, new object[] { (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null) }) as List<TReturn>; return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as List<TReturn>;
} }
public Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) { public Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
var map = new ReadAnonymousTypeInfo(); var map = new ReadAnonymousTypeInfo();
@ -67,7 +67,7 @@ namespace FreeSql.Internal.CommonProvider {
_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString); _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString);
var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic); var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic);
method = method.MakeGenericMethod(typeof(TReturn)); method = method.MakeGenericMethod(typeof(TReturn));
return method.Invoke(_select, new object[] { (map, map.Childs.Count > 0 ? field.Remove(0, 2).ToString() : null) }) as Task<List<TReturn>>; return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task<List<TReturn>>;
} }
public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) { public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<T1>, TReturn>> select) {
@ -77,7 +77,7 @@ namespace FreeSql.Internal.CommonProvider {
_comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString); _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString);
var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) }); 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;
} }

View File

@ -10,6 +10,10 @@ namespace FreeSql.MySql {
public MySqlExpression(CommonUtils common) : base(common) { } public MySqlExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Expression == null) { if (exp.Expression == null) {
switch (exp.Member.Name) { switch (exp.Member.Name) {

View File

@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Common;
namespace FreeSql.MySql { namespace FreeSql.MySql {
@ -25,8 +26,7 @@ namespace FreeSql.MySql {
public ICache Cache { get; } public ICache Cache { get; }
public ICodeFirst CodeFirst { get; } public ICodeFirst CodeFirst { get; }
public IDbFirst DbFirst { get; } public IDbFirst DbFirst { get; }
public MySqlProvider(IDistributedCache cache, IConfiguration cacheStrategy, string masterConnectionString, string[] slaveConnectionString, ILogger log) { public MySqlProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
CacheStrategy = cacheStrategy;
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.MySql"); if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.MySql");
this.InternalCommonUtils = new MySqlUtils(this); this.InternalCommonUtils = new MySqlUtils(this);
@ -41,7 +41,6 @@ namespace FreeSql.MySql {
internal CommonUtils InternalCommonUtils { get; } internal CommonUtils InternalCommonUtils { get; }
internal CommonExpression InternalCommonExpression { get; } internal CommonExpression InternalCommonExpression { get; }
internal IConfiguration CacheStrategy { get; private set; }
public void Transaction(Action handler) => Ado.Transaction(handler); public void Transaction(Action handler) => Ado.Transaction(handler);

View File

@ -1,9 +1,11 @@
using FreeSql.Internal; using FreeSql.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Npgsql; using Npgsql;
using SafeObjectPool; using SafeObjectPool;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Data.Common; using System.Data.Common;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -25,6 +27,7 @@ namespace FreeSql.PostgreSQL {
} }
static DateTime dt1970 = new DateTime(1970, 1, 1); static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param) { public override object AddslashesProcessParam(object param) {
bool isdic = false;
if (param == null) return "NULL"; if (param == null) return "NULL";
if (param is bool || param is bool?) if (param is bool || param is bool?)
return (bool)param ? "'t'" : "'f'"; return (bool)param ? "'t'" : "'f'";
@ -40,12 +43,25 @@ namespace FreeSql.PostgreSQL {
return ((TimeSpan)param).Ticks / 10; return ((TimeSpan)param).Ticks / 10;
else if (param is TimeSpan?) else if (param is TimeSpan?)
return (param as TimeSpan?).Value.Ticks / 10; 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<string, string>) ||
param is IEnumerable<KeyValuePair<string, string>>) {
var pgdics = isdic ? param as Dictionary<string, string> :
param as IEnumerable<KeyValuePair<string, string>>;
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 sb = new StringBuilder();
var ie = param as IEnumerable; var ie = param as IEnumerable;
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z)); foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString(); return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
} else { }else {
return string.Concat("'", param.ToString().Replace("'", "''"), "'"); return string.Concat("'", param.ToString().Replace("'", "''"), "'");
//if (param is string) return string.Concat('N', nparms[a]); //if (param is string) return string.Concat('N', nparms[a]);
} }

View File

@ -1,15 +1,136 @@
using FreeSql.Internal; using FreeSql.Internal;
using FreeSql.Internal.Model; using FreeSql.Internal.Model;
using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text;
namespace FreeSql.PostgreSQL { namespace FreeSql.PostgreSQL {
class PostgreSQLExpression : CommonExpression { class PostgreSQLExpression : CommonExpression {
public PostgreSQLExpression(CommonUtils common) : base(common) { } public PostgreSQLExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> 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<string, string>).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<string, string>).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<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Expression == null) { if (exp.Expression == null) {
switch (exp.Member.Name) { switch (exp.Member.Name) {

View File

@ -6,6 +6,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Common;
namespace FreeSql.PostgreSQL { namespace FreeSql.PostgreSQL {
@ -25,8 +26,7 @@ namespace FreeSql.PostgreSQL {
public ICache Cache { get; } public ICache Cache { get; }
public ICodeFirst CodeFirst { get; } public ICodeFirst CodeFirst { get; }
public IDbFirst DbFirst { get; } public IDbFirst DbFirst { get; }
public PostgreSQLProvider(IDistributedCache cache, IConfiguration cacheStrategy, string masterConnectionString, string[] slaveConnectionString, ILogger log) { public PostgreSQLProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
CacheStrategy = cacheStrategy;
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.PostgreSQL"); if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.PostgreSQL");
this.InternalCommonUtils = new PostgreSQLUtils(this); this.InternalCommonUtils = new PostgreSQLUtils(this);
@ -41,7 +41,6 @@ namespace FreeSql.PostgreSQL {
internal CommonUtils InternalCommonUtils { get; } internal CommonUtils InternalCommonUtils { get; }
internal CommonExpression InternalCommonExpression { get; } internal CommonExpression InternalCommonExpression { get; }
internal IConfiguration CacheStrategy { get; private set; }
public void Transaction(Action handler) => Ado.Transaction(handler); public void Transaction(Action handler) => Ado.Transaction(handler);

View File

@ -10,6 +10,10 @@ namespace FreeSql.SqlServer {
public SqlServerExpression(CommonUtils common) : base(common) { } public SqlServerExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) { internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Expression == null) { if (exp.Expression == null) {
switch (exp.Member.Name) { switch (exp.Member.Name) {

View File

@ -25,8 +25,7 @@ namespace FreeSql.SqlServer {
public ICache Cache { get; } public ICache Cache { get; }
public ICodeFirst CodeFirst { get; } public ICodeFirst CodeFirst { get; }
public IDbFirst DbFirst { get; } public IDbFirst DbFirst { get; }
public SqlServerProvider(IDistributedCache cache, IConfiguration cacheStrategy, string masterConnectionString, string[] slaveConnectionString, ILogger log) { public SqlServerProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
CacheStrategy = cacheStrategy;
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.SqlServer"); if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.SqlServer");
this.InternalCommonUtils = new SqlServerUtils(this); this.InternalCommonUtils = new SqlServerUtils(this);
@ -41,7 +40,6 @@ namespace FreeSql.SqlServer {
internal CommonUtils InternalCommonUtils { get; } internal CommonUtils InternalCommonUtils { get; }
internal CommonExpression InternalCommonExpression { get; } internal CommonExpression InternalCommonExpression { get; }
internal IConfiguration CacheStrategy { get; private set; }
public void Transaction(Action handler) => Ado.Transaction(handler); public void Transaction(Action handler) => Ado.Transaction(handler);

View File

@ -23,6 +23,10 @@ IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.MySql, connstr) .UseConnectionString(FreeSql.DataType.MySql, connstr)
.UseSlave("connectionString1", "connectionString2") //使用从数据库,支持多个 .UseSlave("connectionString1", "connectionString2") //使用从数据库,支持多个
.UseMonitorCommand(
cmd => Console.WriteLine(cmd.CommandText), //监听SQL命令对象在执行前
(cmd, traceLog) => Console.WriteLine(traceLog)) //监听SQL命令对象在执行后
.UseLogger(null) //使用日志,不指定默认输出控制台 ILogger .UseLogger(null) //使用日志,不指定默认输出控制台 ILogger
.UseCache(null) //使用缓存,不指定默认使用内存 IDistributedCache .UseCache(null) //使用缓存,不指定默认使用内存 IDistributedCache