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("\");");