From 703b9aeafa3ef162db34aa64438bcda886048d6b Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Thu, 14 Apr 2022 11:30:23 +0800 Subject: [PATCH] update pgsql json POCO test --- Examples/base_entity/Program.cs | 99 ++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 5b9294b5..35984858 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -11,7 +11,9 @@ using System.Data.Odbc; using System.Data.SqlClient; using System.Data.SQLite; using System.Diagnostics; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; @@ -107,11 +109,32 @@ namespace base_entity public DateTime createtime { get; set; } } + public class SomeEntity + { + [Column(IsIdentity = true)] + public int Id { get; set; } + [Column(MapType = typeof(JToken))] + public Customer Customer { get; set; } + } + + public class Customer // Mapped to a JSON column in the table + { + public string Name { get; set; } + public int Age { get; set; } + public Order[] Orders { get; set; } + } + + public class Order // Part of the JSON column + { + public decimal Price { get; set; } + public string ShippingAddress { get; set; } + } + static void Main(string[] args) { #region 初始化 IFreeSql var fsql = new FreeSql.FreeSqlBuilder() - .UseAutoSyncStructure(true) + //.UseAutoSyncStructure(true) .UseNoneCommandParameter(true) .UseConnectionString(FreeSql.DataType.Sqlite, "data source=test1.db;max pool size=5") @@ -123,8 +146,8 @@ namespace base_entity //.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3") - //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") - //.UseNameConvert(FreeSql.Internal.NameConvertType.ToLower) + .UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") + .UseNameConvert(FreeSql.Internal.NameConvertType.ToLower) //.UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=2") //.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) @@ -149,6 +172,76 @@ namespace base_entity BaseEntity.Initialization(fsql, () => _asyncUow.Value); #endregion + fsql.Aop.ParseExpression += (_, e) => + { + //解析 POCO Jsonb a.Customer.Name + if (e.Expression is MemberExpression memExp) + { + var parentMemExps = new Stack(); + parentMemExps.Push(memExp); + while (true) + { + switch (memExp.Expression.NodeType) + { + case ExpressionType.MemberAccess: + memExp = memExp.Expression as MemberExpression; + if (memExp == null) return; + parentMemExps.Push(memExp); + break; + case ExpressionType.Parameter: + var tb = fsql.CodeFirst.GetTableByEntity(memExp.Expression.Type); + if (tb == null) return; + if (tb.ColumnsByCs.TryGetValue(parentMemExps.Pop().Member.Name, out var trycol) == false) return; + if (new[] { typeof(JToken), typeof(JObject), typeof(JArray) }.Contains(trycol.Attribute.MapType.NullableTypeOrThis()) == false) return; + var tmpcol = tb.ColumnsByPosition.OrderBy(a => a.Attribute.Name.Length).First(); + var result = e.FreeParse(Expression.MakeMemberAccess(memExp.Expression, tb.Properties[tmpcol.CsName])); + result = result.Replace(tmpcol.Attribute.Name, trycol.Attribute.Name); + while (parentMemExps.Any()) + { + memExp = parentMemExps.Pop(); + result = $"{result}->>'{memExp.Member.Name}'"; + } + e.Result = result; + return; + } + } + } + }; + + var methodJsonConvertDeserializeObject = typeof(JsonConvert).GetMethod("DeserializeObject", new[] { typeof(string), typeof(Type) }); + var methodJsonConvertSerializeObject = typeof(JsonConvert).GetMethod("SerializeObject", new[] { typeof(object), typeof(JsonSerializerSettings) }); + var jsonConvertSettings = JsonConvert.DefaultSettings?.Invoke() ?? new JsonSerializerSettings(); + FreeSql.Internal.Utils.dicExecuteArrayRowReadClassOrTuple[typeof(Customer)] = true; + FreeSql.Internal.Utils.GetDataReaderValueBlockExpressionObjectToStringIfThenElse.Add((LabelTarget returnTarget, Expression valueExp, Expression elseExp, Type type) => + { + return Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(Customer)), + Expression.Return(returnTarget, Expression.Call(methodJsonConvertSerializeObject, Expression.Convert(valueExp, typeof(object)), Expression.Constant(jsonConvertSettings)), typeof(object)), + elseExp); + }); + FreeSql.Internal.Utils.GetDataReaderValueBlockExpressionSwitchTypeFullName.Add((LabelTarget returnTarget, Expression valueExp, Type type) => + { + if (type == typeof(Customer)) return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(methodJsonConvertDeserializeObject, Expression.Convert(valueExp, typeof(string)), Expression.Constant(type)), type)); + return null; + }); + + var seid = fsql.Insert(new SomeEntity + { + Customer = JsonConvert.DeserializeObject(@"{ + ""Age"": 25, + ""Name"": ""Joe"", + ""Orders"": [ + { ""OrderPrice"": 9, ""ShippingAddress"": ""Some address 1"" }, + { ""OrderPrice"": 23, ""ShippingAddress"": ""Some address 2"" } + ] +}") + }).ExecuteIdentity(); + var selist = fsql.Select().ToList(); + + var joes = fsql.Select() + .Where(e => e.Customer.Name == "Joe") + .ToSql(); + var testitems = new[] { new AsTableLog{ msg = "msg01", createtime = DateTime.Parse("2022-1-1 13:00:11") },