From b93a487e2f69fea00fa96c39aec6e2fe67cce5e1 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Mon, 6 Jun 2022 15:17:46 +0800 Subject: [PATCH] add PgArrayToMany LazyLoding test #1145 --- FreeSql.DbContext/FreeSql.DbContext.xml | 9 -- .../PostgreSQLPgArrayToManyTest .cs | 120 ++++++++++++++++++ FreeSql/Internal/CommonExpression.cs | 2 +- FreeSql/Internal/UtilsExpressionTree.cs | 20 ++- 4 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 FreeSql.Tests/FreeSql.Tests/PostgreSQL/PostgreSQLPgArrayToManyTest .cs diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 1ab5bf1cf..6b638cad4 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -795,14 +795,5 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/PostgreSQLPgArrayToManyTest .cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/PostgreSQLPgArrayToManyTest .cs new file mode 100644 index 000000000..4ea569570 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/PostgreSQLPgArrayToManyTest .cs @@ -0,0 +1,120 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.PostgreSQL +{ + public class PostgreSQLPgArrayToManyTest + { + + [Table(Name = "pgarray_tomany_user_lazyloading")] + public class UserLazyLoading + { + public int Id { get; set; } + public int[] RoleIds { get; set; } + public string UserName { get; set; } + + [Navigate(nameof(RoleIds))] + public virtual List Roles { get; set; } + } + + [Table(Name = "pgarray_tomany_role_lazyloading")] + public class RoleLazyLoading + { + public int Id { get; set; } + public string RoleName { get; set; } + + [Navigate(nameof(UserLazyLoading.RoleIds))] + public virtual List Users { get; set; } + } + + [Fact] + public void LazyLoading() + { + var fsql = g.pgsql; + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Delete().Where("1=1").ExecuteAffrows(); + + var roles = new[] + { + new RoleLazyLoading { Id = 1, RoleName = "role1" }, + new RoleLazyLoading { Id = 2, RoleName = "role2" }, + new RoleLazyLoading { Id = 3, RoleName = "role3" } + }; + Assert.Equal(3, fsql.Insert(roles).ExecuteAffrows()); + var users = new[] + { + new UserLazyLoading { Id = 11, RoleIds = new [] { 1,2 }, UserName = "user1" }, + new UserLazyLoading { Id = 12, RoleIds = new [] { 1,2,3 }, UserName = "user2" }, + new UserLazyLoading { Id = 13, RoleIds = new [] { 1,3 }, UserName = "user3" }, + new UserLazyLoading { Id = 14, RoleIds = new [] { 3,2,1 }, UserName = "user4" }, + new UserLazyLoading { Id = 15, RoleIds = null, UserName = "user5" }, + new UserLazyLoading { Id = 16, RoleIds = new int[0], UserName = "user6" }, + }; + Assert.Equal(6, fsql.Insert(users).ExecuteAffrows()); + + var role = fsql.Select().Where(a => a.Id == 1).First(); + Assert.IsNotType(role); + + var users2 = role.Users; + Assert.Equal(4, users2.Count); + Assert.Equal(11, users2[0].Id); + Assert.Equal("user1", users2[0].UserName); + Assert.Equal("1,2", string.Join(",", users2[0].RoleIds)); + Assert.Equal(12, users2[1].Id); + Assert.Equal("user2", users2[1].UserName); + Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds)); + Assert.Equal(13, users2[2].Id); + Assert.Equal("user3", users2[2].UserName); + Assert.Equal("1,3", string.Join(",", users2[2].RoleIds)); + Assert.Equal(14, users2[3].Id); + Assert.Equal("user4", users2[3].UserName); + Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds)); + + var roles2 = users2[0].Roles; + Assert.Equal(2, roles2.Count); + Assert.Equal(1, roles2[0].Id); + Assert.Equal("role1", roles2[0].RoleName); + Assert.Equal(2, roles2[1].Id); + Assert.Equal("role2", roles2[1].RoleName); + + roles2 = users2[1].Roles; + Assert.Equal(3, roles2.Count); + Assert.Equal(1, roles2[0].Id); + Assert.Equal("role1", roles2[0].RoleName); + Assert.Equal(2, roles2[1].Id); + Assert.Equal("role2", roles2[1].RoleName); + Assert.Equal(3, roles2[2].Id); + Assert.Equal("role3", roles2[2].RoleName); + + roles2 = users2[2].Roles; + Assert.Equal(2, roles2.Count); + Assert.Equal(1, roles2[0].Id); + Assert.Equal("role1", roles2[0].RoleName); + Assert.Equal(3, roles2[1].Id); + Assert.Equal("role3", roles2[1].RoleName); + + roles2 = users2[3].Roles; + Assert.Equal(3, roles2.Count); + Assert.Equal(3, roles2[0].Id); + Assert.Equal("role3", roles2[0].RoleName); + Assert.Equal(2, roles2[1].Id); + Assert.Equal("role2", roles2[1].RoleName); + Assert.Equal(1, roles2[2].Id); + Assert.Equal("role1", roles2[2].RoleName); + + var user = fsql.Select().Where(a => a.Id == 11).First(); + Assert.IsNotType(user); + + roles2 = user.Roles; + Assert.Equal(2, roles2.Count); + Assert.Equal(1, roles2[0].Id); + Assert.Equal("role1", roles2[0].RoleName); + Assert.Equal(2, roles2[1].Id); + Assert.Equal("role2", roles2[1].RoleName); + } + } +} diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index b7918b54e..30c34799a 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -2201,7 +2201,7 @@ void LocalSetSelectProviderAlias(string alias) midSelect.Where($"{midSelect._tables[0].Alias}.{commonExp._common.QuoteSqlName(memberTbref.MiddleColumns[memberTbref.Columns.Count + tidx].Attribute.Name)} = {select._tables[0].Alias}.{commonExp._common.QuoteSqlName(memberTbref.RefColumns[tidx].Attribute.Name)}"); for (var tidx = 0; tidx < memberTbref.Columns.Count; tidx++) midSelect.Where($"{midSelect._tables[0].Alias}.{commonExp._common.QuoteSqlName(memberTbref.MiddleColumns[tidx].Attribute.Name)} = {mtmReftbname}.{commonExp._common.QuoteSqlName(memberTbref.Columns[tidx].Attribute.Name)}"); - select.Where($"exists({midSelect.ToSql("1").Replace(" \r\n", " \r\n ")})"); + select._where.Append($" AND exists({midSelect.ToSql("1").Replace(" \r\n", " \r\n ")})"); break; case TableRefType.OneToMany: var omtReftbname = e.FreeParse(Expression.MakeMemberAccess(memberExp.Expression, exp3Tb.Properties[exp3Tb.ColumnsByPosition[0].CsName])); diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 7e852d3be..5262560dc 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -969,9 +969,10 @@ public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo .Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {"); if (nvref.Exception == null) - cscode.Append(" base.").Append(pnv.Name).Append(" = __fsql_orm__.Select<").Append(propElementType.DisplayCsharp()) + cscode.Append(" var loc2 = __fsql_orm__.Select<").Append(propElementType.DisplayCsharp()) .Append(">().Where(a => __fsql_orm__.Select<").Append(tbmid.Type.DisplayCsharp()) .Append(">().Where(b => ").Append(lmbdWhere.ToString()).AppendLine(").Any()).ToList();") + .Append(" base.").Append(pnv.Name).Append(" = ").AppendLine(propTypeIsObservableCollection ? $"new ObservableCollection<{propElementType.DisplayCsharp()}>(loc2);" : "loc2;") .Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;"); else cscode.Append(" throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");"); @@ -994,7 +995,8 @@ public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo { var isArrayToMany = false; var lmbdWhere = isLazy ? new StringBuilder() : null; - var cscodeExtLogic = ""; + var cscodeExtLogic1 = ""; + var cscodeExtLogic2 = ""; //Pgsql Array[] To Many if (common._orm.Ado.DataType == DataType.PostgreSQL) { @@ -1042,7 +1044,8 @@ public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo isArrayToMany = trycol != null; if (isArrayToMany) { - cscodeExtLogic = $" if (this.{trycol.CsName} == null) return null; \r\nif (this.{trycol.CsName}.Any() == false) return new {(propTypeIsObservableCollection ? "ObservableCollection" : "List")}<{propElementType.DisplayCsharp()}>();\r\n"; + cscodeExtLogic1 = $" if (this.{trycol.CsName} == null) return null; \r\nif (this.{trycol.CsName}.Any() == false) return new {(propTypeIsObservableCollection ? "ObservableCollection" : "List")}<{propElementType.DisplayCsharp()}>();\r\n"; + cscodeExtLogic2 = $" loc2 = this.{trycol.CsName}.Select(a => loc2.FirstOrDefault(b => b.{tbref.Primarys[0].CsName} == a)).ToList();"; lmbdWhere.Append("this.").Append(trycol.CsName).Append(".Contains(a.").Append(tbref.Primarys[0].CsName); if (trycol.CsType.GetElementType().IsNullableType() == false && tbref.Primarys[0].CsType.IsNullableType()) lmbdWhere.Append(".Value"); lmbdWhere.Append(")"); @@ -1092,7 +1095,7 @@ public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo if (trycol.CsType.GetElementType().IsNullableType() == false && trytb.Primarys[0].CsType.IsNullableType()) { lmbdWhere.Append(".Value"); - cscodeExtLogic = $" if (this.{trytb.Primarys[0].CsName} == null) return null;\r\n"; + cscodeExtLogic1 = $" if (this.{trytb.Primarys[0].CsName} == null) return null;\r\n"; } lmbdWhere.Append(")"); nvref.Columns.Add(tbref.Primarys[0]); @@ -1219,12 +1222,14 @@ public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo if (vp?.Item2 == true) { //get 重写 cscode.Append(" ").Append(propGetModification).Append(" get {\r\n") - .Append(cscodeExtLogic) + .Append(cscodeExtLogic1) .Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {"); if (nvref.Exception == null) { - cscode.Append(" base.").Append(pnv.Name).Append(" = __fsql_orm__.Select<").Append(propElementType.DisplayCsharp()).Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToList();"); + cscode.Append(" var loc2 = __fsql_orm__.Select<").Append(propElementType.DisplayCsharp()).Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToList();") + .Append(cscodeExtLogic2) + .Append(" base.").Append(pnv.Name).Append(" = ").AppendLine(propTypeIsObservableCollection ? $"new ObservableCollection<{propElementType.DisplayCsharp()}>(loc2);" : "loc2;"); if (refprop != null) { cscode.Append(" foreach (var loc1 in base.").Append(pnv.Name).AppendLine(")") @@ -1381,7 +1386,8 @@ public static void AddTableRef(CommonUtils common, TableInfo trytb, PropertyInfo .Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {"); if (nvref.Exception == null) - cscode.Append(" base.").Append(pnv.Name).Append(" = __fsql_orm__.Select<").Append(propTypeName).Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToOne();") + cscode.Append(" var loc3 = __fsql_orm__.Select<").Append(propTypeName).Append(">().Where(a => ").Append(lmbdWhere.ToString()).AppendLine(").ToOne();") + .Append(" base.").Append(pnv.Name).AppendLine(" = loc3;") .Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;"); else cscode.Append(" throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");");