mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 18:52:50 +08:00
Merge pull request #1148 from dotnetcore/PgArrayToMany
Add PgArrayToMany Navigate Objects #1145
This commit is contained in:
commit
4a1886473d
@ -155,8 +155,9 @@ namespace FreeSql
|
||||
if (tref == null) return;
|
||||
switch (tref.RefType)
|
||||
{
|
||||
case Internal.Model.TableRefType.OneToOne:
|
||||
case Internal.Model.TableRefType.ManyToOne:
|
||||
case TableRefType.OneToOne:
|
||||
case TableRefType.ManyToOne:
|
||||
case TableRefType.PgArrayToMany:
|
||||
throw new ArgumentException(DbContextStrings.PropertyOfType_IsNot_OneToManyOrManyToMany(_table.Type.FullName, propertyName));
|
||||
}
|
||||
|
||||
@ -166,7 +167,7 @@ namespace FreeSql
|
||||
try
|
||||
{
|
||||
await AddOrUpdateNavigateAsync(item, false, propertyName, cancellationToken);
|
||||
if (tref.RefType == Internal.Model.TableRefType.OneToMany)
|
||||
if (tref.RefType == TableRefType.OneToMany)
|
||||
{
|
||||
await DbContextFlushCommandAsync(cancellationToken);
|
||||
//删除没有保存的数据,求出主体的条件
|
||||
@ -213,7 +214,7 @@ namespace FreeSql
|
||||
DbSet<object> refSet = null;
|
||||
switch (tref.RefType)
|
||||
{
|
||||
case Internal.Model.TableRefType.OneToOne:
|
||||
case TableRefType.OneToOne:
|
||||
refSet = GetDbSetObject(tref.RefEntityType);
|
||||
var propValItem = GetItemValue(item, prop);
|
||||
if (propValItem == null) return;
|
||||
@ -225,7 +226,8 @@ namespace FreeSql
|
||||
if (isAdd) await refSet.AddAsync(propValItem);
|
||||
else await refSet.AddOrUpdateAsync(propValItem);
|
||||
return;
|
||||
case Internal.Model.TableRefType.ManyToOne:
|
||||
case TableRefType.ManyToOne:
|
||||
case TableRefType.PgArrayToMany:
|
||||
return;
|
||||
}
|
||||
|
||||
@ -234,7 +236,7 @@ namespace FreeSql
|
||||
refSet = GetDbSetObject(tref.RefEntityType);
|
||||
switch (tref.RefType)
|
||||
{
|
||||
case Internal.Model.TableRefType.ManyToMany:
|
||||
case TableRefType.ManyToMany:
|
||||
var curList = new List<object>();
|
||||
foreach (var propValItem in propValEach)
|
||||
{
|
||||
@ -327,7 +329,7 @@ namespace FreeSql
|
||||
await midSet.AddRangeAsync(midListAdd, cancellationToken);
|
||||
}
|
||||
break;
|
||||
case Internal.Model.TableRefType.OneToMany:
|
||||
case TableRefType.OneToMany:
|
||||
var addList = new List<object>();
|
||||
var addOrUpdateList = new List<object>();
|
||||
foreach (var propValItem in propValEach)
|
||||
|
@ -166,8 +166,9 @@ namespace FreeSql
|
||||
if (tref == null) return;
|
||||
switch (tref.RefType)
|
||||
{
|
||||
case Internal.Model.TableRefType.OneToOne:
|
||||
case Internal.Model.TableRefType.ManyToOne:
|
||||
case TableRefType.OneToOne:
|
||||
case TableRefType.ManyToOne:
|
||||
case TableRefType.PgArrayToMany:
|
||||
throw new ArgumentException(DbContextStrings.PropertyOfType_IsNot_OneToManyOrManyToMany(_table.Type.FullName, propertyName));
|
||||
}
|
||||
|
||||
@ -177,7 +178,7 @@ namespace FreeSql
|
||||
try
|
||||
{
|
||||
AddOrUpdateNavigate(item, false, propertyName);
|
||||
if (tref.RefType == Internal.Model.TableRefType.OneToMany)
|
||||
if (tref.RefType == TableRefType.OneToMany)
|
||||
{
|
||||
DbContextFlushCommand();
|
||||
//删除没有保存的数据,求出主体的条件
|
||||
@ -224,7 +225,7 @@ namespace FreeSql
|
||||
DbSet<object> refSet = null;
|
||||
switch (tref.RefType)
|
||||
{
|
||||
case Internal.Model.TableRefType.OneToOne:
|
||||
case TableRefType.OneToOne:
|
||||
refSet = GetDbSetObject(tref.RefEntityType);
|
||||
var propValItem = GetItemValue(item, prop);
|
||||
if (propValItem == null) return;
|
||||
@ -236,7 +237,8 @@ namespace FreeSql
|
||||
if (isAdd) refSet.Add(propValItem);
|
||||
else refSet.AddOrUpdate(propValItem);
|
||||
return;
|
||||
case Internal.Model.TableRefType.ManyToOne:
|
||||
case TableRefType.ManyToOne:
|
||||
case TableRefType.PgArrayToMany:
|
||||
return;
|
||||
}
|
||||
|
||||
@ -714,7 +716,7 @@ namespace FreeSql
|
||||
{
|
||||
return tb.Properties.Where(a => tb.ColumnsByCs.ContainsKey(a.Key) == false)
|
||||
.Select(a => new NativeTuple<TableRef, PropertyInfo>(tb.GetTableRef(a.Key, false), a.Value))
|
||||
.Where(a => a.Item1 != null && a.Item1.RefType != TableRefType.ManyToOne)
|
||||
.Where(a => a.Item1 != null && new[] { TableRefType.OneToOne, TableRefType.OneToMany, TableRefType.ManyToMany }.Contains(a.Item1.RefType))
|
||||
.ToList();
|
||||
}
|
||||
void LocalEach(DbSet<object> dbset, IEnumerable<object> items, bool isOneToOne)
|
||||
@ -860,6 +862,12 @@ namespace FreeSql
|
||||
}
|
||||
}
|
||||
|
||||
var atms = navs.Where(a => a.Item1.RefType == TableRefType.PgArrayToMany).ToList();
|
||||
if (atms.Any())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (dbset == rootDbSet)
|
||||
{
|
||||
if (CanRemove(data, true) == false) return;
|
||||
|
@ -795,14 +795,5 @@
|
||||
<param name="that"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
|
||||
<summary>
|
||||
批量注入 Repository,可以参考代码自行调整
|
||||
</summary>
|
||||
<param name="services"></param>
|
||||
<param name="globalDataFilter"></param>
|
||||
<param name="assemblies"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
|
@ -44,7 +44,7 @@ namespace FreeSql.Tests.Issues
|
||||
FacilityCount = a.Sum(a.Value.FacilityCount),
|
||||
FacilityOpenCount = a.Sum(a.Value.FacilityOpenCount)
|
||||
});
|
||||
Assert.Equal(@"SELECT a.`Dot`, sum(a.`FacilityCount`) as1, sum(a.`FacilityOpenCount`) as2
|
||||
Assert.Equal(@"SELECT a.`Dot` as1, sum(a.`FacilityCount`) as2, sum(a.`FacilityOpenCount`) as3
|
||||
FROM `ts_facility` a
|
||||
WHERE (a.`Date` = cast(date_format('2020-12-30 00:00:00.000','%Y-%m-%d') as datetime)) AND (((a.`EnterpriseId`) in (5))) AND (a.`FacilityType` = 1)
|
||||
GROUP BY a.`Dot`", sql);
|
||||
|
@ -0,0 +1,275 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace FreeSql.Tests.PostgreSQL.PgArrayToMany
|
||||
{
|
||||
public class LazyLoadingTest
|
||||
{
|
||||
|
||||
[Table(Name = "pgarray_tomany_user_lazyloading")]
|
||||
public class User
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int UserId { get; set; }
|
||||
public int[] RoleIds { get; set; }
|
||||
public string UserName { get; set; }
|
||||
|
||||
[Navigate(nameof(RoleIds))]
|
||||
public virtual List<Role> Roles { get; set; }
|
||||
}
|
||||
|
||||
[Table(Name = "pgarray_tomany_role_lazyloading")]
|
||||
public class Role
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int RoleId { get; set; }
|
||||
public string RoleName { get; set; }
|
||||
|
||||
[Navigate(nameof(User.RoleIds))]
|
||||
public virtual List<User> Users { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LazyLoading()
|
||||
{
|
||||
var fsql = g.pgsql;
|
||||
fsql.Delete<User>().Where("1=1").ExecuteAffrows();
|
||||
fsql.Delete<Role>().Where("1=1").ExecuteAffrows();
|
||||
|
||||
var roles = new[]
|
||||
{
|
||||
new Role { RoleId = 1, RoleName = "role1" },
|
||||
new Role { RoleId = 2, RoleName = "role2" },
|
||||
new Role { RoleId = 3, RoleName = "role3" }
|
||||
};
|
||||
Assert.Equal(3, fsql.Insert(roles).ExecuteAffrows());
|
||||
var users = new[]
|
||||
{
|
||||
new User { UserId = 11, RoleIds = new [] { 1,2 }, UserName = "user1" },
|
||||
new User { UserId = 12, RoleIds = new [] { 1,2,3 }, UserName = "user2" },
|
||||
new User { UserId = 13, RoleIds = new [] { 1,3 }, UserName = "user3" },
|
||||
new User { UserId = 14, RoleIds = new [] { 3,2,1 }, UserName = "user4" },
|
||||
new User { UserId = 15, RoleIds = null, UserName = "user5" },
|
||||
new User { UserId = 16, RoleIds = new int[0], UserName = "user6" },
|
||||
};
|
||||
Assert.Equal(6, fsql.Insert(users).ExecuteAffrows());
|
||||
|
||||
var users5Select = fsql.Select<User>().Where(a => a.Roles.Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_lazyloading"" b
|
||||
WHERE (a.""roleids"" @> ARRAY[b.""roleid""]::int4[]) AND (b.""rolename"" = 'role1')
|
||||
limit 1))", users5Select.ToSql());
|
||||
var users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
users5Select = fsql.Select<User>().Where(a => a.Roles.AsSelect().Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_lazyloading"" b
|
||||
WHERE (b.""rolename"" = 'role1') AND (a.""roleids"" @> ARRAY[b.""roleid""]::int4[])
|
||||
limit 1))", users5Select.ToSql());
|
||||
users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
|
||||
var roles5Select = fsql.Select<Role>().Where(a => a.Users.Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_lazyloading"" b
|
||||
WHERE (b.""roleids"" @> ARRAY[a.""roleid""]::int4[]) AND (b.""username"" = 'user1')
|
||||
limit 1))", roles5Select.ToSql());
|
||||
var roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
roles5Select = fsql.Select<Role>().Where(a => a.Users.AsSelect().Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_lazyloading"" b
|
||||
WHERE (b.""username"" = 'user1') AND (b.""roleids"" @> ARRAY[a.""roleid""]::int4[])
|
||||
limit 1))", roles5Select.ToSql());
|
||||
roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
|
||||
|
||||
var users4 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList(a => new
|
||||
{
|
||||
user = a, roles = a.Roles
|
||||
});
|
||||
var roles4 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList(a => new
|
||||
{
|
||||
role = a,
|
||||
users = a.Users
|
||||
});
|
||||
|
||||
|
||||
var users3 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList();
|
||||
Assert.Equal(6, users3.Count);
|
||||
var users2 = users3;
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal(15, users2[4].UserId);
|
||||
Assert.Equal(16, users2[5].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("user5", users2[4].UserName);
|
||||
Assert.Equal("user6", users2[5].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
Assert.Null(users2[4].RoleIds);
|
||||
Assert.Empty(users2[5].RoleIds);
|
||||
|
||||
var roles2 = users3[0].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[1].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
roles2 = users3[2].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(3, roles2[1].RoleId);
|
||||
Assert.Equal("role3", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[3].Roles;
|
||||
Assert.Equal(3, roles2[0].RoleId);
|
||||
Assert.Equal("role3", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(1, roles2[2].RoleId);
|
||||
Assert.Equal("role1", roles2[2].RoleName);
|
||||
|
||||
Assert.Null(users3[4].Roles);
|
||||
Assert.Empty(users3[5].Roles);
|
||||
|
||||
var roles3 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList();
|
||||
Assert.Equal(3, roles3.Count);
|
||||
roles2 = roles3;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
users2 = roles2[0].Users;
|
||||
Assert.Equal(4, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
|
||||
users2 = roles2[1].Users;
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
users2 = roles2[2].Users;
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(12, users2[0].UserId);
|
||||
Assert.Equal("user2", users2[0].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(13, users2[1].UserId);
|
||||
Assert.Equal("user3", users2[1].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
var role = fsql.Select<Role>().Where(a => a.RoleId == 1).First();
|
||||
Assert.IsNotType<Role>(role);
|
||||
|
||||
users2 = role.Users;
|
||||
Assert.Equal(4, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
|
||||
roles2 = users2[0].Roles;
|
||||
Assert.Equal(2, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
|
||||
roles2 = users2[1].Roles;
|
||||
Assert.Equal(3, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
roles2 = users2[2].Roles;
|
||||
Assert.Equal(2, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(3, roles2[1].RoleId);
|
||||
Assert.Equal("role3", roles2[1].RoleName);
|
||||
|
||||
roles2 = users2[3].Roles;
|
||||
Assert.Equal(3, roles2.Count);
|
||||
Assert.Equal(3, roles2[0].RoleId);
|
||||
Assert.Equal("role3", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(1, roles2[2].RoleId);
|
||||
Assert.Equal("role1", roles2[2].RoleName);
|
||||
|
||||
var user = fsql.Select<User>().Where(a => a.UserId == 11).First();
|
||||
Assert.IsNotType<User>(user);
|
||||
|
||||
roles2 = user.Roles;
|
||||
Assert.Equal(2, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace FreeSql.Tests.PostgreSQL.PgArrayToMany
|
||||
{
|
||||
public class NormalTest
|
||||
{
|
||||
|
||||
[Table(Name = "pgarray_tomany_user_normal")]
|
||||
public class User
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int UserId { get; set; }
|
||||
public int[] RoleIds { get; set; }
|
||||
public string UserName { get; set; }
|
||||
|
||||
[Navigate(nameof(RoleIds))]
|
||||
public List<Role> Roles { get; set; }
|
||||
}
|
||||
|
||||
[Table(Name = "pgarray_tomany_role_normal")]
|
||||
public class Role
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int RoleId { get; set; }
|
||||
public string RoleName { get; set; }
|
||||
|
||||
[Navigate(nameof(User.RoleIds))]
|
||||
public List<User> Users { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Normal()
|
||||
{
|
||||
var fsql = g.pgsql;
|
||||
fsql.Delete<User>().Where("1=1").ExecuteAffrows();
|
||||
fsql.Delete<Role>().Where("1=1").ExecuteAffrows();
|
||||
|
||||
var roles = new[]
|
||||
{
|
||||
new Role { RoleId = 1, RoleName = "role1" },
|
||||
new Role { RoleId = 2, RoleName = "role2" },
|
||||
new Role { RoleId = 3, RoleName = "role3" }
|
||||
};
|
||||
Assert.Equal(3, fsql.Insert(roles).ExecuteAffrows());
|
||||
var users = new[]
|
||||
{
|
||||
new User { UserId = 11, RoleIds = new [] { 1,2 }, UserName = "user1" },
|
||||
new User { UserId = 12, RoleIds = new [] { 1,2,3 }, UserName = "user2" },
|
||||
new User { UserId = 13, RoleIds = new [] { 1,3 }, UserName = "user3" },
|
||||
new User { UserId = 14, RoleIds = new [] { 3,2,1 }, UserName = "user4" },
|
||||
new User { UserId = 15, RoleIds = null, UserName = "user5" },
|
||||
new User { UserId = 16, RoleIds = new int[0], UserName = "user6" },
|
||||
};
|
||||
Assert.Equal(6, fsql.Insert(users).ExecuteAffrows());
|
||||
|
||||
var users5Select = fsql.Select<User>().Where(a => a.Roles.Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_normal"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_normal"" b
|
||||
WHERE (a.""roleids"" @> ARRAY[b.""roleid""]::int4[]) AND (b.""rolename"" = 'role1')
|
||||
limit 1))", users5Select.ToSql());
|
||||
var users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
users5Select = fsql.Select<User>().Where(a => a.Roles.AsSelect().Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_normal"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_normal"" b
|
||||
WHERE (b.""rolename"" = 'role1') AND (a.""roleids"" @> ARRAY[b.""roleid""]::int4[])
|
||||
limit 1))", users5Select.ToSql());
|
||||
users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
|
||||
var roles5Select = fsql.Select<Role>().Where(a => a.Users.Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_normal"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_normal"" b
|
||||
WHERE (b.""roleids"" @> ARRAY[a.""roleid""]::int4[]) AND (b.""username"" = 'user1')
|
||||
limit 1))", roles5Select.ToSql());
|
||||
var roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
roles5Select = fsql.Select<Role>().Where(a => a.Users.AsSelect().Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_normal"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_normal"" b
|
||||
WHERE (b.""username"" = 'user1') AND (b.""roleids"" @> ARRAY[a.""roleid""]::int4[])
|
||||
limit 1))", roles5Select.ToSql());
|
||||
roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
|
||||
|
||||
var users4 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList(a => new
|
||||
{
|
||||
user = a, roles = a.Roles
|
||||
});
|
||||
var roles4 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList(a => new
|
||||
{
|
||||
role = a,
|
||||
users = a.Users
|
||||
});
|
||||
|
||||
|
||||
var users3 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList();
|
||||
Assert.Equal(6, users3.Count);
|
||||
var users2 = users3;
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal(15, users2[4].UserId);
|
||||
Assert.Equal(16, users2[5].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("user5", users2[4].UserName);
|
||||
Assert.Equal("user6", users2[5].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
Assert.Null(users2[4].RoleIds);
|
||||
Assert.Empty(users2[5].RoleIds);
|
||||
|
||||
var roles2 = users3[0].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[1].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
roles2 = users3[2].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(3, roles2[1].RoleId);
|
||||
Assert.Equal("role3", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[3].Roles;
|
||||
Assert.Equal(3, roles2[0].RoleId);
|
||||
Assert.Equal("role3", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(1, roles2[2].RoleId);
|
||||
Assert.Equal("role1", roles2[2].RoleName);
|
||||
|
||||
Assert.Null(users3[4].Roles);
|
||||
Assert.Empty(users3[5].Roles);
|
||||
|
||||
var roles3 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList();
|
||||
Assert.Equal(3, roles3.Count);
|
||||
roles2 = roles3;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
users2 = roles2[0].Users;
|
||||
Assert.Equal(4, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
|
||||
users2 = roles2[1].Users;
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
users2 = roles2[2].Users;
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(12, users2[0].UserId);
|
||||
Assert.Equal("user2", users2[0].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(13, users2[1].UserId);
|
||||
Assert.Equal("user3", users2[1].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
var role = fsql.Select<Role>().Where(a => a.RoleId == 1).First();
|
||||
Assert.IsType<Role>(role);
|
||||
|
||||
var user = fsql.Select<User>().Where(a => a.UserId == 11).First();
|
||||
Assert.IsType<User>(user);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,275 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace FreeSql.Tests.PostgreSQL.PgArrayToMany
|
||||
{
|
||||
public class ObservableCollectionLazyLoadingTest
|
||||
{
|
||||
|
||||
[Table(Name = "pgarray_tomany_user_observablecollection_lazyloading")]
|
||||
public class User
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int UserId { get; set; }
|
||||
public int[] RoleIds { get; set; }
|
||||
public string UserName { get; set; }
|
||||
|
||||
[Navigate(nameof(RoleIds))]
|
||||
public virtual List<Role> Roles { get; set; }
|
||||
}
|
||||
|
||||
[Table(Name = "pgarray_tomany_role_observablecollection_lazyloading")]
|
||||
public class Role
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int RoleId { get; set; }
|
||||
public string RoleName { get; set; }
|
||||
|
||||
[Navigate(nameof(User.RoleIds))]
|
||||
public virtual List<User> Users { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ObservableCollectionLazyLoading()
|
||||
{
|
||||
var fsql = g.pgsql;
|
||||
fsql.Delete<User>().Where("1=1").ExecuteAffrows();
|
||||
fsql.Delete<Role>().Where("1=1").ExecuteAffrows();
|
||||
|
||||
var roles = new[]
|
||||
{
|
||||
new Role { RoleId = 1, RoleName = "role1" },
|
||||
new Role { RoleId = 2, RoleName = "role2" },
|
||||
new Role { RoleId = 3, RoleName = "role3" }
|
||||
};
|
||||
Assert.Equal(3, fsql.Insert(roles).ExecuteAffrows());
|
||||
var users = new[]
|
||||
{
|
||||
new User { UserId = 11, RoleIds = new [] { 1,2 }, UserName = "user1" },
|
||||
new User { UserId = 12, RoleIds = new [] { 1,2,3 }, UserName = "user2" },
|
||||
new User { UserId = 13, RoleIds = new [] { 1,3 }, UserName = "user3" },
|
||||
new User { UserId = 14, RoleIds = new [] { 3,2,1 }, UserName = "user4" },
|
||||
new User { UserId = 15, RoleIds = null, UserName = "user5" },
|
||||
new User { UserId = 16, RoleIds = new int[0], UserName = "user6" },
|
||||
};
|
||||
Assert.Equal(6, fsql.Insert(users).ExecuteAffrows());
|
||||
|
||||
var users5Select = fsql.Select<User>().Where(a => a.Roles.Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_observablecollection_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_observablecollection_lazyloading"" b
|
||||
WHERE (a.""roleids"" @> ARRAY[b.""roleid""]::int4[]) AND (b.""rolename"" = 'role1')
|
||||
limit 1))", users5Select.ToSql());
|
||||
var users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
users5Select = fsql.Select<User>().Where(a => a.Roles.AsSelect().Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_observablecollection_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_observablecollection_lazyloading"" b
|
||||
WHERE (b.""rolename"" = 'role1') AND (a.""roleids"" @> ARRAY[b.""roleid""]::int4[])
|
||||
limit 1))", users5Select.ToSql());
|
||||
users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
|
||||
var roles5Select = fsql.Select<Role>().Where(a => a.Users.Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_observablecollection_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_observablecollection_lazyloading"" b
|
||||
WHERE (b.""roleids"" @> ARRAY[a.""roleid""]::int4[]) AND (b.""username"" = 'user1')
|
||||
limit 1))", roles5Select.ToSql());
|
||||
var roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
roles5Select = fsql.Select<Role>().Where(a => a.Users.AsSelect().Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_observablecollection_lazyloading"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_observablecollection_lazyloading"" b
|
||||
WHERE (b.""username"" = 'user1') AND (b.""roleids"" @> ARRAY[a.""roleid""]::int4[])
|
||||
limit 1))", roles5Select.ToSql());
|
||||
roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
|
||||
|
||||
var users4 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList(a => new
|
||||
{
|
||||
user = a, roles = a.Roles
|
||||
});
|
||||
var roles4 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList(a => new
|
||||
{
|
||||
role = a,
|
||||
users = a.Users
|
||||
});
|
||||
|
||||
|
||||
var users3 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList();
|
||||
Assert.Equal(6, users3.Count);
|
||||
var users2 = users3;
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal(15, users2[4].UserId);
|
||||
Assert.Equal(16, users2[5].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("user5", users2[4].UserName);
|
||||
Assert.Equal("user6", users2[5].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
Assert.Null(users2[4].RoleIds);
|
||||
Assert.Empty(users2[5].RoleIds);
|
||||
|
||||
var roles2 = users3[0].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[1].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
roles2 = users3[2].Roles;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(3, roles2[1].RoleId);
|
||||
Assert.Equal("role3", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[3].Roles;
|
||||
Assert.Equal(3, roles2[0].RoleId);
|
||||
Assert.Equal("role3", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(1, roles2[2].RoleId);
|
||||
Assert.Equal("role1", roles2[2].RoleName);
|
||||
|
||||
Assert.Null(users3[4].Roles);
|
||||
Assert.Empty(users3[5].Roles);
|
||||
|
||||
var roles3 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList();
|
||||
Assert.Equal(3, roles3.Count);
|
||||
roles2 = roles3;
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
users2 = roles2[0].Users;
|
||||
Assert.Equal(4, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
|
||||
users2 = roles2[1].Users;
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
users2 = roles2[2].Users;
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(12, users2[0].UserId);
|
||||
Assert.Equal("user2", users2[0].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(13, users2[1].UserId);
|
||||
Assert.Equal("user3", users2[1].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
var role = fsql.Select<Role>().Where(a => a.RoleId == 1).First();
|
||||
Assert.IsNotType<Role>(role);
|
||||
|
||||
users2 = role.Users;
|
||||
Assert.Equal(4, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
|
||||
roles2 = users2[0].Roles;
|
||||
Assert.Equal(2, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
|
||||
roles2 = users2[1].Roles;
|
||||
Assert.Equal(3, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
roles2 = users2[2].Roles;
|
||||
Assert.Equal(2, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(3, roles2[1].RoleId);
|
||||
Assert.Equal("role3", roles2[1].RoleName);
|
||||
|
||||
roles2 = users2[3].Roles;
|
||||
Assert.Equal(3, roles2.Count);
|
||||
Assert.Equal(3, roles2[0].RoleId);
|
||||
Assert.Equal("role3", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(1, roles2[2].RoleId);
|
||||
Assert.Equal("role1", roles2[2].RoleName);
|
||||
|
||||
var user = fsql.Select<User>().Where(a => a.UserId == 11).First();
|
||||
Assert.IsNotType<User>(user);
|
||||
|
||||
roles2 = user.Roles;
|
||||
Assert.Equal(2, roles2.Count);
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace FreeSql.Tests.PostgreSQL.PgArrayToMany
|
||||
{
|
||||
public class ObservableCollectionTest
|
||||
{
|
||||
|
||||
[Table(Name = "pgarray_tomany_user_observablecollection")]
|
||||
public class User
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int UserId { get; set; }
|
||||
public int[] RoleIds { get; set; }
|
||||
public string UserName { get; set; }
|
||||
|
||||
[Navigate(nameof(RoleIds))]
|
||||
public ObservableCollection<Role> Roles { get; set; }
|
||||
}
|
||||
|
||||
[Table(Name = "pgarray_tomany_role_observablecollection")]
|
||||
public class Role
|
||||
{
|
||||
[Column(IsPrimary = true)]
|
||||
public int RoleId { get; set; }
|
||||
public string RoleName { get; set; }
|
||||
|
||||
[Navigate(nameof(User.RoleIds))]
|
||||
public ObservableCollection<User> Users { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ObservableCollection()
|
||||
{
|
||||
var fsql = g.pgsql;
|
||||
fsql.Delete<User>().Where("1=1").ExecuteAffrows();
|
||||
fsql.Delete<Role>().Where("1=1").ExecuteAffrows();
|
||||
|
||||
var roles = new[]
|
||||
{
|
||||
new Role { RoleId = 1, RoleName = "role1" },
|
||||
new Role { RoleId = 2, RoleName = "role2" },
|
||||
new Role { RoleId = 3, RoleName = "role3" }
|
||||
};
|
||||
Assert.Equal(3, fsql.Insert(roles).ExecuteAffrows());
|
||||
var users = new[]
|
||||
{
|
||||
new User { UserId = 11, RoleIds = new [] { 1,2 }, UserName = "user1" },
|
||||
new User { UserId = 12, RoleIds = new [] { 1,2,3 }, UserName = "user2" },
|
||||
new User { UserId = 13, RoleIds = new [] { 1,3 }, UserName = "user3" },
|
||||
new User { UserId = 14, RoleIds = new [] { 3,2,1 }, UserName = "user4" },
|
||||
new User { UserId = 15, RoleIds = null, UserName = "user5" },
|
||||
new User { UserId = 16, RoleIds = new int[0], UserName = "user6" },
|
||||
};
|
||||
Assert.Equal(6, fsql.Insert(users).ExecuteAffrows());
|
||||
|
||||
var users5Select = fsql.Select<User>().Where(a => a.Roles.Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_observablecollection"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_observablecollection"" b
|
||||
WHERE (a.""roleids"" @> ARRAY[b.""roleid""]::int4[]) AND (b.""rolename"" = 'role1')
|
||||
limit 1))", users5Select.ToSql());
|
||||
var users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
users5Select = fsql.Select<User>().Where(a => a.Roles.AsSelect().Any(b => b.RoleName == "role1"));
|
||||
Assert.Equal(@"SELECT a.""userid"", a.""roleids"", a.""username""
|
||||
FROM ""pgarray_tomany_user_observablecollection"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_role_observablecollection"" b
|
||||
WHERE (b.""rolename"" = 'role1') AND (a.""roleids"" @> ARRAY[b.""roleid""]::int4[])
|
||||
limit 1))", users5Select.ToSql());
|
||||
users5 = users5Select.ToList();
|
||||
Assert.Equal(4, users5.Count);
|
||||
|
||||
var roles5Select = fsql.Select<Role>().Where(a => a.Users.Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_observablecollection"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_observablecollection"" b
|
||||
WHERE (b.""roleids"" @> ARRAY[a.""roleid""]::int4[]) AND (b.""username"" = 'user1')
|
||||
limit 1))", roles5Select.ToSql());
|
||||
var roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
roles5Select = fsql.Select<Role>().Where(a => a.Users.AsSelect().Any(b => b.UserName == "user1"));
|
||||
Assert.Equal(@"SELECT a.""roleid"", a.""rolename""
|
||||
FROM ""pgarray_tomany_role_observablecollection"" a
|
||||
WHERE (exists(SELECT 1
|
||||
FROM ""pgarray_tomany_user_observablecollection"" b
|
||||
WHERE (b.""username"" = 'user1') AND (b.""roleids"" @> ARRAY[a.""roleid""]::int4[])
|
||||
limit 1))", roles5Select.ToSql());
|
||||
roles5 = roles5Select.ToList();
|
||||
Assert.Equal(2, roles5.Count);
|
||||
|
||||
|
||||
var users4 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList(a => new
|
||||
{
|
||||
user = a,
|
||||
roles = a.Roles
|
||||
});
|
||||
var roles4 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList(a => new
|
||||
{
|
||||
role = a,
|
||||
users = a.Users
|
||||
});
|
||||
|
||||
|
||||
var users3 = fsql.Select<User>().IncludeMany(a => a.Roles).ToList();
|
||||
Assert.Equal(6, users3.Count);
|
||||
var users2 = users3;
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal(15, users2[4].UserId);
|
||||
Assert.Equal(16, users2[5].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("user5", users2[4].UserName);
|
||||
Assert.Equal("user6", users2[5].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
Assert.Null(users2[4].RoleIds);
|
||||
Assert.Empty(users2[5].RoleIds);
|
||||
|
||||
var roles2 = users3[0].Roles.ToList();
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[1].Roles.ToList();
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
roles2 = users3[2].Roles.ToList();
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(3, roles2[1].RoleId);
|
||||
Assert.Equal("role3", roles2[1].RoleName);
|
||||
|
||||
roles2 = users3[3].Roles.ToList();
|
||||
Assert.Equal(3, roles2[0].RoleId);
|
||||
Assert.Equal("role3", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(1, roles2[2].RoleId);
|
||||
Assert.Equal("role1", roles2[2].RoleName);
|
||||
|
||||
Assert.Null(users3[4].Roles);
|
||||
Assert.Empty(users3[5].Roles);
|
||||
|
||||
var roles3 = fsql.Select<Role>().IncludeMany(a => a.Users).ToList();
|
||||
Assert.Equal(3, roles3.Count);
|
||||
roles2 = roles3.ToList();
|
||||
Assert.Equal(1, roles2[0].RoleId);
|
||||
Assert.Equal("role1", roles2[0].RoleName);
|
||||
Assert.Equal(2, roles2[1].RoleId);
|
||||
Assert.Equal("role2", roles2[1].RoleName);
|
||||
Assert.Equal(3, roles2[2].RoleId);
|
||||
Assert.Equal("role3", roles2[2].RoleName);
|
||||
|
||||
users2 = roles2[0].Users.ToList();
|
||||
Assert.Equal(4, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(13, users2[2].UserId);
|
||||
Assert.Equal("user3", users2[2].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[2].RoleIds));
|
||||
Assert.Equal(14, users2[3].UserId);
|
||||
Assert.Equal("user4", users2[3].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[3].RoleIds));
|
||||
|
||||
users2 = roles2[1].Users.ToList();
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(11, users2[0].UserId);
|
||||
Assert.Equal("user1", users2[0].UserName);
|
||||
Assert.Equal("1,2", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(12, users2[1].UserId);
|
||||
Assert.Equal("user2", users2[1].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
users2 = roles2[2].Users.ToList();
|
||||
Assert.Equal(3, users2.Count);
|
||||
Assert.Equal(12, users2[0].UserId);
|
||||
Assert.Equal("user2", users2[0].UserName);
|
||||
Assert.Equal("1,2,3", string.Join(",", users2[0].RoleIds));
|
||||
Assert.Equal(13, users2[1].UserId);
|
||||
Assert.Equal("user3", users2[1].UserName);
|
||||
Assert.Equal("1,3", string.Join(",", users2[1].RoleIds));
|
||||
Assert.Equal(14, users2[2].UserId);
|
||||
Assert.Equal("user4", users2[2].UserName);
|
||||
Assert.Equal("3,2,1", string.Join(",", users2[2].RoleIds));
|
||||
|
||||
var role = fsql.Select<Role>().Where(a => a.RoleId == 1).First();
|
||||
Assert.IsType<Role>(role);
|
||||
|
||||
var user = fsql.Select<User>().Where(a => a.UserId == 11).First();
|
||||
Assert.IsType<User>(user);
|
||||
}
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@ public static partial class FreeSqlGlobalExtensions
|
||||
});
|
||||
public static bool IsIntegerType(this Type that) => that == null ? false : (_dicIsNumberType.Value.TryGetValue(that, out var tryval) ? tryval : false);
|
||||
public static bool IsNumberType(this Type that) => that == null ? false : _dicIsNumberType.Value.ContainsKey(that);
|
||||
public static bool IsNullableType(this Type that) => that.IsArray == false && that?.FullName.StartsWith("System.Nullable`1[") == true;
|
||||
public static bool IsNullableType(this Type that) => that == null ? false : (that.IsArray == false && that.FullName.StartsWith("System.Nullable`1[") == true);
|
||||
public static bool IsAnonymousType(this Type that) => that == null ? false : (that.FullName.StartsWith("<>f__AnonymousType") || that.FullName.StartsWith("VB$AnonymousType"));
|
||||
public static bool IsArrayOrList(this Type that) => that == null ? false : (that.IsArray || typeof(IList).IsAssignableFrom(that));
|
||||
public static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GetGenericArguments().First() : that;
|
||||
|
@ -3303,6 +3303,177 @@
|
||||
<param name="parms"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteConnectTestAsync(System.Int32,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
测试数据库是否连接正确,本方法执行如下命令:<para></para>
|
||||
MySql/SqlServer/PostgreSQL/达梦/人大金仓/神通: SELECT 1<para></para>
|
||||
Oracle: SELECT 1 FROM dual<para></para>
|
||||
</summary>
|
||||
<param name="commandTimeout">命令超时设置(秒)</param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns>true: 成功, false: 失败</returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{FreeSql.Internal.Model.FetchCallbackArgs{System.Data.Common.DbDataReader},System.Threading.Tasks.Task},System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
|
||||
</summary>
|
||||
<param name="readerHander"></param>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{FreeSql.Internal.Model.FetchCallbackArgs{System.Data.Common.DbDataReader},System.Threading.Tasks.Task},System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="readerHander"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询
|
||||
</summary>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询
|
||||
</summary>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询
|
||||
</summary>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
在【主库】执行
|
||||
</summary>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
在【主库】执行
|
||||
</summary>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.QueryAsync``1(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 })
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.QueryAsync``1(System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<typeparam name="T"></typeparam>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.QueryAsync``2(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<typeparam name="T2"></typeparam>
|
||||
<param name="cmdType"></param>
|
||||
<param name="cmdText"></param>
|
||||
<param name="cmdParms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.QueryAsync``2(System.String,System.Object,System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
执行SQL返回对象集合,Query<User, Address>("select * from user where age > @age; select * from address", new { age = 25 })<para></para>
|
||||
提示:parms 参数还可以传 Dictionary<string, object>
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<typeparam name="T2"></typeparam>
|
||||
<param name="cmdText"></param>
|
||||
<param name="parms"></param>
|
||||
<param name="cancellationToken"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="E:FreeSql.IAop.ParseExpression">
|
||||
<summary>
|
||||
可自定义解析表达式
|
||||
@ -4269,6 +4440,23 @@
|
||||
中间表,多对多
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.Model.TableRefType.PgArrayToMany">
|
||||
<summary>
|
||||
PostgreSQL 数组类型专属功能<para></para>
|
||||
方式一:select * from Role where Id in (RoleIds)<para></para>
|
||||
class User {<para></para>
|
||||
____public int[] RoleIds { get; set; }<para></para>
|
||||
____[Navigate(nameof(RoleIds))]<para></para>
|
||||
____public List<Role> Roles { get; set; }<para></para>
|
||||
}<para></para>
|
||||
方式二:select * from User where RoleIds @> Id<para></para>
|
||||
class Role {<para></para>
|
||||
____public int Id { get; set; }<para></para>
|
||||
____[Navigate(nameof(User.RoleIds))]<para></para>
|
||||
____public List<User> Users { get; set; }<para></para>
|
||||
}<para></para>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Internal.ObjectPool.IObjectPool`1.IsAvailable">
|
||||
<summary>
|
||||
是否可用
|
||||
@ -4309,6 +4497,12 @@
|
||||
<param name="timeout">超时</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.GetAsync">
|
||||
<summary>
|
||||
获取资源
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)">
|
||||
<summary>
|
||||
使用完毕后,归还资源
|
||||
@ -4384,6 +4578,12 @@
|
||||
</summary>
|
||||
<param name="obj">资源对象</param>
|
||||
</member>
|
||||
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnGetAsync(FreeSql.Internal.ObjectPool.Object{`0})">
|
||||
<summary>
|
||||
从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
|
||||
</summary>
|
||||
<param name="obj">资源对象</param>
|
||||
</member>
|
||||
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})">
|
||||
<summary>
|
||||
归还对象给对象池的时候触发
|
||||
|
@ -154,6 +154,7 @@ namespace FreeSql.Internal
|
||||
{
|
||||
case TableRefType.ManyToMany:
|
||||
case TableRefType.OneToMany:
|
||||
case TableRefType.PgArrayToMany:
|
||||
continue;
|
||||
}
|
||||
if (_tables.Any(a => a.Alias == $"{map.First().Table.Alias}__{memProp.Name}") == false) continue;
|
||||
@ -1194,20 +1195,43 @@ namespace FreeSql.Internal
|
||||
if (fsql != null)
|
||||
{
|
||||
if (asSelectParentExp != null)
|
||||
{ //执行 AsSelect() 的关联,OneToMany,ManyToMany
|
||||
{
|
||||
//执行 AsSelect() 的关联,OneToMany,ManyToMany,PgArrayToMany
|
||||
if (fsqltables[0].Parameter == null)
|
||||
{
|
||||
fsqltables[0].Alias = $"tb_{fsqltables.Count}";
|
||||
fsqltables[0].Parameter = Expression.Parameter(asSelectEntityType, fsqltables[0].Alias);
|
||||
}
|
||||
var fsqlWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(asSelectEntityType, asSelectEntityType3 =>
|
||||
typeof(ISelect<>).MakeGenericType(asSelectEntityType3).GetMethod("Where", new[] {
|
||||
typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(asSelectEntityType3, typeof(bool)))
|
||||
}));
|
||||
|
||||
var parm123Tb = _common.GetTableByEntity(asSelectParentExp.Type);
|
||||
var parm123Ref = parm123Tb.GetTableRef(asSelectParentExp1.Member.Name, true);
|
||||
if (parm123Ref != null)
|
||||
{
|
||||
if (parm123Ref.RefType == TableRefType.PgArrayToMany)
|
||||
{
|
||||
var amtReftbname = ExpressionLambdaToSql(Expression.MakeMemberAccess(asSelectParentExp, parm123Tb.Properties[parm123Tb.ColumnsByPosition[0].CsName]), tsc);
|
||||
amtReftbname = amtReftbname.Substring(0, amtReftbname.Length - _common.QuoteSqlName(parm123Tb.ColumnsByPosition[0].Attribute.Name).Length - 1);
|
||||
if (parm123Ref.RefColumns[0] == fsqltables[0].Table.Primarys[0])
|
||||
{
|
||||
var dbinfo = _common._orm.CodeFirst.GetDbInfo(parm123Ref.Columns[0].CsType);
|
||||
(fsql as Select0Provider)._where.Append(" AND (").Append($"{amtReftbname}.{_common.QuoteSqlName(parm123Ref.Columns[0].Attribute.Name)} @> ARRAY[{fsqltables[0].Alias}.{_common.QuoteSqlName(parm123Ref.RefColumns[0].Attribute.Name)}]::{dbinfo?.dbtype}").Append(")");
|
||||
}
|
||||
else if (parm123Ref.Columns[0] == parm123Tb.Primarys[0])
|
||||
{
|
||||
var dbinfo = _common._orm.CodeFirst.GetDbInfo(parm123Ref.RefColumns[0].CsType);
|
||||
(fsql as Select0Provider)._where.Append(" AND (").Append($"{fsqltables[0].Alias}.{_common.QuoteSqlName(parm123Ref.RefColumns[0].Attribute.Name)} @> ARRAY[{amtReftbname}.{_common.QuoteSqlName(parm123Ref.Columns[0].Attribute.Name)}]::{dbinfo?.dbtype}").Append(")");
|
||||
}
|
||||
else
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var fsqlWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(asSelectEntityType, asSelectEntityType3 =>
|
||||
typeof(ISelect<>).MakeGenericType(asSelectEntityType3).GetMethod("Where", new[] {
|
||||
typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(asSelectEntityType3, typeof(bool)))
|
||||
}));
|
||||
var fsqlWhereParam = fsqltables.First().Parameter; //Expression.Parameter(asSelectEntityType);
|
||||
Expression fsqlWhereExp = null;
|
||||
if (parm123Ref.RefType == TableRefType.ManyToMany)
|
||||
@ -1352,6 +1376,7 @@ namespace FreeSql.Internal
|
||||
fsqlWhere.Invoke(fsql, new object[] { Expression.Lambda(fsqlWhereExp, fsqlWhereParam) });
|
||||
}
|
||||
}
|
||||
}
|
||||
asSelectBefores.Clear();
|
||||
|
||||
switch (exp3.Method.Name)
|
||||
@ -2186,7 +2211,7 @@ namespace FreeSql.Internal
|
||||
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]));
|
||||
@ -2194,6 +2219,24 @@ namespace FreeSql.Internal
|
||||
for (var tidx = 0; tidx < memberTbref.Columns.Count; tidx++)
|
||||
select.Where($"{select._tables[0].Alias}.{commonExp._common.QuoteSqlName(memberTbref.RefColumns[tidx].Attribute.Name)} = {omtReftbname}.{commonExp._common.QuoteSqlName(memberTbref.Columns[tidx].Attribute.Name)}");
|
||||
break;
|
||||
case TableRefType.PgArrayToMany:
|
||||
var amtReftbname = e.FreeParse(Expression.MakeMemberAccess(memberExp.Expression, exp3Tb.Properties[exp3Tb.ColumnsByPosition[0].CsName]));
|
||||
amtReftbname = amtReftbname.Substring(0, amtReftbname.Length - commonExp._common.QuoteSqlName(exp3Tb.ColumnsByPosition[0].Attribute.Name).Length - 1);
|
||||
if (memberTbref.RefColumns[0] == select._tables[0].Table.Primarys[0])
|
||||
{
|
||||
var dbinfo = commonExp._common._orm.CodeFirst.GetDbInfo(memberTbref.Columns[0].CsType);
|
||||
select.Where($"{amtReftbname}.{commonExp._common.QuoteSqlName(memberTbref.Columns[0].Attribute.Name)} @> ARRAY[{select._tables[0].Alias}.{commonExp._common.QuoteSqlName(memberTbref.RefColumns[0].Attribute.Name)}]::{dbinfo?.dbtype}");
|
||||
}
|
||||
else if (memberTbref.Columns[0] == exp3Tb.Primarys[0])
|
||||
{
|
||||
var dbinfo = commonExp._common._orm.CodeFirst.GetDbInfo(memberTbref.RefColumns[0].CsType);
|
||||
select.Where($"{select._tables[0].Alias}.{commonExp._common.QuoteSqlName(memberTbref.RefColumns[0].Attribute.Name)} @> ARRAY[{amtReftbname}.{commonExp._common.QuoteSqlName(memberTbref.Columns[0].Attribute.Name)}]::{dbinfo?.dbtype}");
|
||||
}
|
||||
else
|
||||
{
|
||||
;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
@ -2241,6 +2284,10 @@ namespace FreeSql.Internal
|
||||
if (select != null) return;
|
||||
LocalInitSelectProvider();
|
||||
continue;
|
||||
case TableRefType.PgArrayToMany:
|
||||
if (select != null) return;
|
||||
LocalInitSelectProvider();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (exp4.NodeType == ExpressionType.Call)
|
||||
|
@ -222,6 +222,17 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var bindings = new List<MemberBinding>();
|
||||
if (imni.IsOutputPrimary) bindings.AddRange(imni.Table.Primarys.Select(a => Expression.Bind(imni.Table.Properties[a.CsName], Expression.MakeMemberAccess(imni.CurrentExpression, imni.Table.Properties[a.CsName]))));
|
||||
if (imni.Childs.Any()) bindings.AddRange(imni.Childs.Select(a => Expression.Bind(imni.Table.Properties[a.Key], GetIncludeManyNewInitExpression(a.Value))));
|
||||
var pgarrayToManys = imni.Table.GetAllTableRef().Select(tr =>
|
||||
{
|
||||
if (tr.Value.RefType != TableRefType.PgArrayToMany) return null;
|
||||
var reftb = _orm.CodeFirst.GetTableByEntity(tr.Value.RefEntityType);
|
||||
if (tr.Value.RefColumns[0] == reftb.Primarys[0])
|
||||
{
|
||||
bindings.Add(Expression.Bind(imni.Table.Properties[tr.Value.Columns[0].CsName], Expression.MakeMemberAccess(imni.CurrentExpression, imni.Table.Properties[tr.Value.Columns[0].CsName])));
|
||||
return tr.Key;
|
||||
}
|
||||
return null;
|
||||
}).ToList();
|
||||
return Expression.MemberInit(imni.Table.Type.InternalNewExpression(), bindings);
|
||||
}
|
||||
|
||||
@ -418,6 +429,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
case TableRefType.ManyToMany:
|
||||
case TableRefType.OneToMany:
|
||||
case TableRefType.PgArrayToMany:
|
||||
var funcType = typeof(Func<,>).MakeGenericType(_tables[0].Table.Type, typeof(IEnumerable<>).MakeGenericType(parTbref.RefEntityType));
|
||||
var navigateSelector = Expression.Lambda(funcType, exp, _tables[0].Parameter);
|
||||
var incMethod = this.GetType().GetMethod("IncludeMany");
|
||||
@ -668,10 +680,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
//members.Clear(); 此行影响 ToChunk 第二次
|
||||
|
||||
var isObservableCollection = collMem.Type == typeof(ObservableCollection<TNavigate>);
|
||||
var listValueExp = Expression.Parameter(typeof(List<TNavigate>), "listValue");
|
||||
var setListValue = membersExpNotNull == null ?
|
||||
Expression.Lambda<Action<T1, List<TNavigate>>>(
|
||||
collMem.Type == typeof(ObservableCollection<TNavigate>) ?
|
||||
isObservableCollection ?
|
||||
(Expression)Expression.IfThen(
|
||||
Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List<TNavigate>))),
|
||||
Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection<TNavigate>).GetConstructor(new[] { typeof(List<TNavigate>) }), listValueExp))
|
||||
@ -679,7 +692,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.TypeAs(listValueExp, collMem.Type))
|
||||
, t1parm, listValueExp).Compile() :
|
||||
Expression.Lambda<Action<T1, List<TNavigate>>>(Expression.IfThen(membersExpNotNull,
|
||||
collMem.Type == typeof(ObservableCollection<TNavigate>) ?
|
||||
isObservableCollection ?
|
||||
(Expression)Expression.IfThen(
|
||||
Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List<TNavigate>))),
|
||||
Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection<TNavigate>).GetConstructor(new[] { typeof(List<TNavigate>) }), listValueExp))
|
||||
@ -1172,6 +1185,128 @@ namespace FreeSql.Internal.CommonProvider
|
||||
dicList.Clear();
|
||||
}
|
||||
break;
|
||||
case TableRefType.PgArrayToMany:
|
||||
if (true)
|
||||
{
|
||||
var subList = new List<TNavigate>();
|
||||
var tbref2 = _commonUtils.GetTableByEntity(tbref.RefEntityType);
|
||||
if (tbref.RefColumns[0] == tbref2.Primarys[0])
|
||||
{
|
||||
var listKeys = list.Select(a =>
|
||||
{
|
||||
var arrVal = getListValue(a, tbref.Columns[0].CsName, 0) as Array;
|
||||
if (arrVal == null) return null;
|
||||
var arrObjVal = new object[arrVal.Length];
|
||||
arrVal.CopyTo(arrObjVal, 0);
|
||||
return arrObjVal;
|
||||
}).ToArray();
|
||||
var arrExp = Expression.NewArrayInit(tbref.RefColumns[0].CsType, listKeys.Where(a => a != null).SelectMany(a => a).Distinct()
|
||||
.Select(a => Expression.Constant(Utils.GetDataReaderValue(tbref.RefColumns[0].CsType, a), tbref.RefColumns[0].CsType)).ToArray());
|
||||
var otmExpParm1 = Expression.Parameter(typeof(TNavigate), "a");
|
||||
var containsMethod = _dicTypeMethod.GetOrAdd(tbref.RefColumns[0].CsType, et => new ConcurrentDictionary<string, MethodInfo>()).GetOrAdd("Contains", mn =>
|
||||
typeof(Enumerable).GetMethods().Where(a => a.Name == mn).First()).MakeGenericMethod(tbref.RefColumns[0].CsType);
|
||||
var refCol = Expression.MakeMemberAccess(otmExpParm1, tbref2.Properties[tbref.RefColumns[0].CsName]);
|
||||
subSelect.Where(Expression.Lambda<Func<TNavigate, bool>>(
|
||||
Expression.Call(null, containsMethod, arrExp, refCol), otmExpParm1));
|
||||
|
||||
if (isAsync)
|
||||
{
|
||||
#if net40
|
||||
#else
|
||||
if (selectExp == null) subList = await subSelect.ToListAsync(true, cancellationToken);
|
||||
else subList = await subSelect.ToListAsync<TNavigate>(selectExp, cancellationToken);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectExp == null) subList = subSelect.ToList(true);
|
||||
else subList = subSelect.ToList<TNavigate>(selectExp);
|
||||
}
|
||||
|
||||
if (subList.Any() == false)
|
||||
{
|
||||
foreach (var item in list)
|
||||
setListValue(item, new List<TNavigate>());
|
||||
return;
|
||||
}
|
||||
var dicSubList = subList.ToDictionary(a => EntityUtilExtensions.GetEntityValueWithPropertyName(_orm, tbref.RefEntityType, a, tbref.RefColumns[0].CsName)?.ToString(), a => a);
|
||||
|
||||
var parentNavs = new List<string>();
|
||||
foreach (var navProp in tbref2.Properties)
|
||||
{
|
||||
if (tbref2.ColumnsByCs.ContainsKey(navProp.Key)) continue;
|
||||
if (tbref2.ColumnsByCsIgnore.ContainsKey(navProp.Key)) continue;
|
||||
var tr2ref = tbref2.GetTableRef(navProp.Key, false);
|
||||
if (tr2ref == null) continue;
|
||||
if (tr2ref.RefType != TableRefType.ManyToOne) continue;
|
||||
if (tr2ref.RefEntityType != tb.Type) continue;
|
||||
if (string.Join(",", tr2ref.Columns.Select(a => a.CsName).OrderBy(a => a)) != string.Join(",", tbref.RefColumns.Select(a => a.CsName).OrderBy(a => a))) continue; //- 修复 IncludeMany 只填充子属性中双向关系的 ManyToOne 对象值;防止把 ManyToOne 多个相同类型的导航属性值都填充了
|
||||
parentNavs.Add(navProp.Key);
|
||||
}
|
||||
for (var y = 0; y < list.Count; y++)
|
||||
{
|
||||
var item = list[y];
|
||||
var dicListKeys = listKeys[y];
|
||||
if (dicListKeys == null) continue;
|
||||
var navs = new List<TNavigate>();
|
||||
foreach (var dlk in dicListKeys)
|
||||
{
|
||||
if (dlk == null)
|
||||
{
|
||||
navs.Add(null);
|
||||
continue;
|
||||
}
|
||||
var dicListKey = dlk.ToString();
|
||||
dicSubList.TryGetValue(dicListKey, out var nav);
|
||||
navs.Add(nav);
|
||||
}
|
||||
setListValue(item, navs);
|
||||
}
|
||||
dicSubList.Clear();
|
||||
subList.Clear();
|
||||
}
|
||||
else if (tbref.Columns[0] == tb.Primarys[0])
|
||||
{
|
||||
var listKeys = list.Select(a => getListValue(a, tbref.Columns[0].CsName, 0)).Distinct()
|
||||
.Select(a => Utils.GetDataReaderValue(tbref.RefColumns[0].CsType.GetElementType(), a)).ToArray();
|
||||
var listKeysSql = _commonUtils.GetNoneParamaterSqlValue(subSelect._params, "arrtm", tbref.RefColumns[0], tbref.RefColumns[0].CsType, listKeys);
|
||||
subSelect.Where($"{subSelectT1Alias}.{_commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name)} && {listKeysSql}");
|
||||
|
||||
if (isAsync)
|
||||
{
|
||||
#if net40
|
||||
#else
|
||||
if (selectExp == null) subList = await subSelect.ToListAsync(true, cancellationToken);
|
||||
else subList = await subSelect.ToListAsync<TNavigate>(selectExp, cancellationToken);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectExp == null) subList = subSelect.ToList(true);
|
||||
else subList = subSelect.ToList<TNavigate>(selectExp);
|
||||
}
|
||||
|
||||
if (subList.Any() == false)
|
||||
{
|
||||
foreach (var item in list)
|
||||
setListValue(item, new List<TNavigate>());
|
||||
return;
|
||||
}
|
||||
var subListDic = subList.Select(a => {
|
||||
var arrVal = EntityUtilExtensions.GetEntityValueWithPropertyName(_orm, tbref2.Type, a, tbref.RefColumns[0].CsName) as Array;
|
||||
var arrObjVal = new object[arrVal.Length];
|
||||
arrVal.CopyTo(arrObjVal, 0);
|
||||
return arrObjVal.Select(b => NativeTuple.Create(a, b?.ToString()));
|
||||
}).SelectMany(a => a).GroupBy(a => a.Item2).ToDictionary(a => a.Key, a => a.Select(b => b.Item1).ToList());
|
||||
foreach (var item in list)
|
||||
{
|
||||
var itemKey = getListValue(item, tbref.Columns[0].CsName, 0)?.ToString();
|
||||
subListDic.TryGetValue(itemKey, out var navs);
|
||||
setListValue(item, navs);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,7 @@ namespace FreeSql.Internal.Model
|
||||
}
|
||||
return tryref;
|
||||
}
|
||||
public IEnumerable<KeyValuePair<string, TableRef>> GetAllTableRef() => _refs;
|
||||
|
||||
//public void CopyTo(TableInfo target)
|
||||
//{
|
||||
@ -150,6 +151,22 @@ namespace FreeSql.Internal.Model
|
||||
}
|
||||
public enum TableRefType
|
||||
{
|
||||
OneToOne, ManyToOne, OneToMany, ManyToMany
|
||||
OneToOne, ManyToOne, OneToMany, ManyToMany,
|
||||
/// <summary>
|
||||
/// PostgreSQL 数组类型专属功能<para></para>
|
||||
/// 方式一:select * from Role where Id in (RoleIds)<para></para>
|
||||
/// class User {<para></para>
|
||||
/// ____public int[] RoleIds { get; set; }<para></para>
|
||||
/// ____[Navigate(nameof(RoleIds))]<para></para>
|
||||
/// ____public List<Role> Roles { get; set; }<para></para>
|
||||
/// }<para></para>
|
||||
/// 方式二:select * from User where RoleIds @> Id<para></para>
|
||||
/// class Role {<para></para>
|
||||
/// ____public int Id { get; set; }<para></para>
|
||||
/// ____[Navigate(nameof(User.RoleIds))]<para></para>
|
||||
/// ____public List<User> Users { get; set; }<para></para>
|
||||
/// }<para></para>
|
||||
/// </summary>
|
||||
PgArrayToMany
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
@ -593,7 +594,7 @@ namespace FreeSql.Internal
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception(CoreStrings.LazyLoading_CompilationError(trytbTypeName, ex.Message, cscode)); ;
|
||||
throw new Exception(CoreStrings.LazyLoading_CompilationError(trytbTypeName, ex.Message, cscode));
|
||||
}
|
||||
var type = assembly.GetExportedTypes()/*.DefinedTypes*/.Where(a => a.FullName.EndsWith(trytbTypeLazyName)).FirstOrDefault();
|
||||
trytb.TypeLazy = type;
|
||||
@ -623,6 +624,7 @@ namespace FreeSql.Internal
|
||||
|
||||
//List 或 ICollection,一对多、多对多
|
||||
var propElementType = pnv.PropertyType.GetGenericArguments().FirstOrDefault() ?? pnv.PropertyType.GetElementType();
|
||||
var propTypeIsObservableCollection = propElementType != null && pnv.PropertyType == typeof(ObservableCollection<>).MakeGenericType(propElementType);
|
||||
if (propElementType != null)
|
||||
{
|
||||
if (typeof(IEnumerable).IsAssignableFrom(pnv.PropertyType) == false) return;
|
||||
@ -967,9 +969,10 @@ namespace FreeSql.Internal
|
||||
.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("\");");
|
||||
@ -989,8 +992,133 @@ namespace FreeSql.Internal
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //One To Many
|
||||
{
|
||||
var isArrayToMany = false;
|
||||
var lmbdWhere = isLazy ? new StringBuilder() : null;
|
||||
var cscodeExtLogic1 = "";
|
||||
var cscodeExtLogic2 = "";
|
||||
//Pgsql Array[] To Many
|
||||
if (common._orm.Ado.DataType == DataType.PostgreSQL)
|
||||
{
|
||||
//class User {
|
||||
// public int[] RoleIds { get; set; }
|
||||
// [Navigate(nameof(RoleIds))]
|
||||
// public List<Role> Roles { get; set; }
|
||||
//}
|
||||
//class Role {
|
||||
// [Navigate(nameof(User.RoleIds))]
|
||||
// public List<User> Users { get; set; }
|
||||
//}
|
||||
ColumnInfo trycol = null;
|
||||
if (tbref.Primarys.Length == 1)
|
||||
{
|
||||
if (pnvBind?.Length == 1)
|
||||
{
|
||||
if (trytb.ColumnsByCs.TryGetValue(pnvBind[0], out trycol))
|
||||
{
|
||||
if (trycol.CsType.IsArray == false) trycol = null;
|
||||
else if (trycol != null && tbref.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis())
|
||||
{
|
||||
nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,{trytbTypeName}.{trycol.CsName} 数组元素 与 {tbrefTypeName}.{tbref.Primarys[0].CsName} 类型不符");
|
||||
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
|
||||
//if (isLazy) throw nvref.Exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pnvBind == null && trycol == null)
|
||||
{
|
||||
var findtbrefPkCsName = tbref.Primarys[0].CsName.TrimStart('_');
|
||||
if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(trytb.Type.Name.Length).TrimStart('_');
|
||||
var findtrytb = pnv.Name;
|
||||
if (findtrytb.EndsWith($"{tbref.CsName}s", StringComparison.CurrentCultureIgnoreCase)) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1);
|
||||
findtrytb += tbref.CsName;
|
||||
if (
|
||||
trytb.ColumnsByCs.TryGetValue($"{findtrytb}{findtbrefPkCsName}s", out trycol) == false && //骆峰命名
|
||||
trytb.ColumnsByCs.TryGetValue($"{findtrytb}_{findtbrefPkCsName}s", out trycol) == false //下划线命名
|
||||
)
|
||||
{
|
||||
}
|
||||
if (trycol != null && tbref.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis())
|
||||
trycol = null;
|
||||
}
|
||||
isArrayToMany = trycol != null;
|
||||
if (isArrayToMany)
|
||||
{
|
||||
if (isLazy)
|
||||
{
|
||||
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(")");
|
||||
}
|
||||
nvref.Columns.Add(trycol);
|
||||
nvref.RefColumns.Add(tbref.Primarys[0]);
|
||||
nvref.RefEntityType = tbref.Type;
|
||||
nvref.RefType = TableRefType.PgArrayToMany;
|
||||
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
|
||||
}
|
||||
}
|
||||
|
||||
if (nvref.Exception == null && trytb.Primarys.Length == 1 && isArrayToMany == false)
|
||||
{
|
||||
if (pnvBind?.Length == 1)
|
||||
{
|
||||
if (tbref.ColumnsByCs.TryGetValue(pnvBind[0], out trycol))
|
||||
{
|
||||
if (trycol.CsType.IsArray == false) trycol = null;
|
||||
else if (trytb.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis())
|
||||
{
|
||||
nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,{trytbTypeName}.{trytb.Primarys[0].CsName} 与 {tbrefTypeName}.{trycol.CsName} 数组元素类型不符");
|
||||
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
|
||||
//if (isLazy) throw nvref.Exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pnvBind != null && trycol == null)
|
||||
{
|
||||
var findtrytbPkCsName = trytb.Primarys[0].CsName.TrimStart('_');
|
||||
if (findtrytbPkCsName.StartsWith(trytb.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtrytbPkCsName = findtrytbPkCsName.Substring(trytb.Type.Name.Length).TrimStart('_');
|
||||
var findtrytb = pnv.Name;
|
||||
if (findtrytb.EndsWith($"{trytb.CsName}s", StringComparison.CurrentCultureIgnoreCase)) findtrytb = findtrytb.Substring(0, findtrytb.Length - trytb.CsName.Length - 1);
|
||||
findtrytb += trytb.CsName;
|
||||
if (
|
||||
tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}s", out trycol) == false && //骆峰命名
|
||||
tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtrytbPkCsName}s", out trycol) == false //下划线命名
|
||||
)
|
||||
{
|
||||
}
|
||||
if (trycol != null && trytb.Primarys[0].CsType.NullableTypeOrThis() != trycol.CsType.GetElementType().NullableTypeOrThis())
|
||||
trycol = null;
|
||||
}
|
||||
isArrayToMany = trycol != null;
|
||||
if (isArrayToMany)
|
||||
{
|
||||
if (isLazy)
|
||||
{
|
||||
lmbdWhere.Append("a.").Append(trycol.CsName).Append(".Contains(this.").Append(trytb.Primarys[0].CsName);
|
||||
if (trycol.CsType.GetElementType().IsNullableType() == false && trytb.Primarys[0].CsType.IsNullableType())
|
||||
{
|
||||
lmbdWhere.Append(".Value");
|
||||
cscodeExtLogic1 = $" if (this.{trytb.Primarys[0].CsName} == null) return null;\r\n";
|
||||
}
|
||||
lmbdWhere.Append(")");
|
||||
}
|
||||
nvref.Columns.Add(trytb.Primarys[0]);
|
||||
nvref.RefColumns.Add(trycol);
|
||||
nvref.RefEntityType = tbref.Type;
|
||||
nvref.RefType = TableRefType.PgArrayToMany;
|
||||
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PropertyInfo refprop = null;
|
||||
if (isArrayToMany == false)
|
||||
{
|
||||
List<ColumnInfo> bindColumns = new List<ColumnInfo>();
|
||||
//One To Many
|
||||
if (pnvBind != null)
|
||||
{
|
||||
foreach (var bi in pnvBind)
|
||||
@ -1006,10 +1134,8 @@ namespace FreeSql.Internal
|
||||
}
|
||||
}
|
||||
|
||||
PropertyInfo refprop = null;
|
||||
var refcols = tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type);
|
||||
refprop = refcols.Count() == 1 ? refcols.First().Value : null;
|
||||
var lmbdWhere = isLazy ? new StringBuilder() : null;
|
||||
|
||||
if (nvref.Exception == null && bindColumns.Any() && bindColumns.Count != trytb.Primarys.Length)
|
||||
{
|
||||
@ -1094,6 +1220,7 @@ namespace FreeSql.Internal
|
||||
trytb.AddOrUpdateTableRef(pnv.Name, nvref);
|
||||
}
|
||||
|
||||
}
|
||||
if (isLazy)
|
||||
{
|
||||
cscode.Append(" private bool __lazy__").Append(pnv.Name).AppendLine(" = false;")
|
||||
@ -1101,11 +1228,14 @@ namespace FreeSql.Internal
|
||||
if (vp?.Item2 == true)
|
||||
{ //get 重写
|
||||
cscode.Append(" ").Append(propGetModification).Append(" get {\r\n")
|
||||
.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(")")
|
||||
@ -1133,7 +1263,8 @@ namespace FreeSql.Internal
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //一对一、多对一
|
||||
{
|
||||
//一对一、多对一
|
||||
var tbref = pnv.PropertyType == trytb.Type ? trytb : GetTableByEntity(pnv.PropertyType, common); //可能是父子关系
|
||||
if (tbref == null) return;
|
||||
if (tbref.Primarys.Any() == false)
|
||||
@ -1261,7 +1392,8 @@ namespace FreeSql.Internal
|
||||
.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("\");");
|
||||
|
Loading…
x
Reference in New Issue
Block a user