mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	- 补充 支持 ManyToMany 导航属性子查询 ToList;
This commit is contained in:
		@@ -512,14 +512,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>
 | 
			
		||||
 
 | 
			
		||||
@@ -96,6 +96,150 @@ namespace FreeSql.Tests.SqlServerExpression
 | 
			
		||||
            public string name { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void StringJoin02()
 | 
			
		||||
        {
 | 
			
		||||
            var fsql = g.sqlserver;
 | 
			
		||||
            fsql.Delete<StringJoin02User>().Where("1=1").ExecuteAffrows();
 | 
			
		||||
            fsql.Delete<StringJoin02Role>().Where("1=1").ExecuteAffrows();
 | 
			
		||||
            fsql.Delete<StringJoin02UserRole>().Where("1=1").ExecuteAffrows();
 | 
			
		||||
 | 
			
		||||
            var users = fsql.Insert(new[]
 | 
			
		||||
            {
 | 
			
		||||
                new StringJoin02User { UserName = "user01" },
 | 
			
		||||
                new StringJoin02User { UserName = "user02" }
 | 
			
		||||
            }).ExecuteInserted();
 | 
			
		||||
 | 
			
		||||
            var roles = fsql.Insert(new[]
 | 
			
		||||
            {
 | 
			
		||||
                new StringJoin02Role { RoleName = "role01" },
 | 
			
		||||
                new StringJoin02Role { RoleName = "role02" },
 | 
			
		||||
                new StringJoin02Role { RoleName = "role03" }
 | 
			
		||||
            }).ExecuteInserted();
 | 
			
		||||
 | 
			
		||||
            fsql.Insert(new[]
 | 
			
		||||
            {
 | 
			
		||||
                new StringJoin02UserRole{ UserId = users[0].Id, RoleId = roles[0].Id },
 | 
			
		||||
                new StringJoin02UserRole{ UserId = users[0].Id, RoleId = roles[1].Id },
 | 
			
		||||
                new StringJoin02UserRole{ UserId = users[0].Id, RoleId = roles[2].Id },
 | 
			
		||||
 | 
			
		||||
                new StringJoin02UserRole{ UserId = users[1].Id, RoleId = roles[0].Id },
 | 
			
		||||
                new StringJoin02UserRole{ UserId = users[1].Id, RoleId = roles[2].Id },
 | 
			
		||||
            }).ExecuteAffrows();
 | 
			
		||||
 | 
			
		||||
            var repo = fsql.GetRepository<StringJoin02User>();
 | 
			
		||||
            var result = repo.Select.ToList(w =>
 | 
			
		||||
                new
 | 
			
		||||
                {
 | 
			
		||||
                    w.Id,
 | 
			
		||||
                    w.UserName,
 | 
			
		||||
                    <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ɫ = string.Join(",", repo.Orm
 | 
			
		||||
                        .Select<StringJoin02UserRole, StringJoin02Role>()
 | 
			
		||||
                        .LeftJoin((b, c) => b.RoleId == c.Id)
 | 
			
		||||
                        .Where((b, c) => b.UserId == w.Id)
 | 
			
		||||
                        .ToList((b, c) => c.RoleName))
 | 
			
		||||
                });
 | 
			
		||||
            Assert.Equal(2, result.Count);
 | 
			
		||||
            Assert.Equal(users[0].Id, result[0].Id);
 | 
			
		||||
            Assert.Equal("user01", result[0].UserName);
 | 
			
		||||
            Assert.Equal("role01,role02,role03", result[0].<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ɫ);
 | 
			
		||||
 | 
			
		||||
            Assert.Equal(users[1].Id, result[1].Id);
 | 
			
		||||
            Assert.Equal("user02", result[1].UserName);
 | 
			
		||||
            Assert.Equal("role01,role03", result[1].<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ɫ);
 | 
			
		||||
        }
 | 
			
		||||
        class StringJoin02User
 | 
			
		||||
        {
 | 
			
		||||
            [Column(IsIdentity = true)]
 | 
			
		||||
            public int Id { get; set; }
 | 
			
		||||
            public string UserName { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
        class StringJoin02Role
 | 
			
		||||
        {
 | 
			
		||||
            [Column(IsIdentity = true)]
 | 
			
		||||
            public int Id { get; set; }
 | 
			
		||||
            public string RoleName { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
        class StringJoin02UserRole
 | 
			
		||||
        {
 | 
			
		||||
            public int UserId { get; set; }
 | 
			
		||||
            public int RoleId { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void StringJoin03()
 | 
			
		||||
        {
 | 
			
		||||
            var fsql = g.sqlserver;
 | 
			
		||||
            fsql.Delete<StringJoin03User>().Where("1=1").ExecuteAffrows();
 | 
			
		||||
            fsql.Delete<StringJoin03Role>().Where("1=1").ExecuteAffrows();
 | 
			
		||||
            fsql.Delete<StringJoin03UserRole>().Where("1=1").ExecuteAffrows();
 | 
			
		||||
 | 
			
		||||
            var users = fsql.Insert(new[]
 | 
			
		||||
            {
 | 
			
		||||
                new StringJoin03User { UserName = "user01" },
 | 
			
		||||
                new StringJoin03User { UserName = "user02" }
 | 
			
		||||
            }).ExecuteInserted();
 | 
			
		||||
 | 
			
		||||
            var roles = fsql.Insert(new[]
 | 
			
		||||
            {
 | 
			
		||||
                new StringJoin03Role { RoleName = "role01" },
 | 
			
		||||
                new StringJoin03Role { RoleName = "role02" },
 | 
			
		||||
                new StringJoin03Role { RoleName = "role03" }
 | 
			
		||||
            }).ExecuteInserted();
 | 
			
		||||
 | 
			
		||||
            fsql.Insert(new[]
 | 
			
		||||
            {
 | 
			
		||||
                new StringJoin03UserRole{ UserId = users[0].Id, RoleId = roles[0].Id },
 | 
			
		||||
                new StringJoin03UserRole{ UserId = users[0].Id, RoleId = roles[1].Id },
 | 
			
		||||
                new StringJoin03UserRole{ UserId = users[0].Id, RoleId = roles[2].Id },
 | 
			
		||||
 | 
			
		||||
                new StringJoin03UserRole{ UserId = users[1].Id, RoleId = roles[0].Id },
 | 
			
		||||
                new StringJoin03UserRole{ UserId = users[1].Id, RoleId = roles[2].Id },
 | 
			
		||||
            }).ExecuteAffrows();
 | 
			
		||||
 | 
			
		||||
            var repo = fsql.GetRepository<StringJoin03User>();
 | 
			
		||||
            var result = repo.Select.ToList(w =>
 | 
			
		||||
                new
 | 
			
		||||
                {
 | 
			
		||||
                    w.Id,
 | 
			
		||||
                    w.UserName,
 | 
			
		||||
                    <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ɫ = string.Join(",", w.Roles.AsSelect().ToList(b => b.RoleName))
 | 
			
		||||
                });
 | 
			
		||||
            Assert.Equal(2, result.Count);
 | 
			
		||||
            Assert.Equal(users[0].Id, result[0].Id);
 | 
			
		||||
            Assert.Equal("user01", result[0].UserName);
 | 
			
		||||
            Assert.Equal("role01,role02,role03", result[0].<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ɫ);
 | 
			
		||||
 | 
			
		||||
            Assert.Equal(users[1].Id, result[1].Id);
 | 
			
		||||
            Assert.Equal("user02", result[1].UserName);
 | 
			
		||||
            Assert.Equal("role01,role03", result[1].<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ɫ);
 | 
			
		||||
        }
 | 
			
		||||
        class StringJoin03User
 | 
			
		||||
        {
 | 
			
		||||
            [Column(IsIdentity = true)]
 | 
			
		||||
            public int Id { get; set; }
 | 
			
		||||
            public string UserName { get; set; }
 | 
			
		||||
 | 
			
		||||
            [Navigate(ManyToMany = typeof(StringJoin03UserRole))]
 | 
			
		||||
            public List<StringJoin03Role> Roles { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
        class StringJoin03Role
 | 
			
		||||
        {
 | 
			
		||||
            [Column(IsIdentity = true)]
 | 
			
		||||
            public int Id { get; set; }
 | 
			
		||||
            public string RoleName { get; set; }
 | 
			
		||||
 | 
			
		||||
            [Navigate(ManyToMany = typeof(StringJoin03UserRole))]
 | 
			
		||||
            public List<StringJoin03User> Users { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
        class StringJoin03UserRole
 | 
			
		||||
        {
 | 
			
		||||
            public int UserId { get; set; }
 | 
			
		||||
            public int RoleId { get; set; }
 | 
			
		||||
            public StringJoin03User User { get; set; }
 | 
			
		||||
            public StringJoin03Role Role { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void First()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -3133,177 +3133,6 @@
 | 
			
		||||
            <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>
 | 
			
		||||
            可自定义解析表达式
 | 
			
		||||
@@ -4137,12 +3966,6 @@
 | 
			
		||||
            <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>
 | 
			
		||||
            使用完毕后,归还资源
 | 
			
		||||
@@ -4213,12 +4036,6 @@
 | 
			
		||||
            </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>
 | 
			
		||||
            归还对象给对象池的时候触发
 | 
			
		||||
 
 | 
			
		||||
@@ -700,6 +700,7 @@ namespace FreeSql.Internal
 | 
			
		||||
        static ConcurrentDictionary<Type, ConcurrentDictionary<string, bool>> _dicMethodExistsExpressionCallAttribute = new ConcurrentDictionary<Type, ConcurrentDictionary<string, bool>>();
 | 
			
		||||
        static ConcurrentDictionary<Type, FieldInfo[]> _dicTypeExpressionCallClassContextFields = new ConcurrentDictionary<Type, FieldInfo[]>();
 | 
			
		||||
        static ThreadLocal<List<BaseDiyMemberExpression>> _subSelectParentDiyMemExps = new ThreadLocal<List<BaseDiyMemberExpression>>(); //子查询的所有父自定义查询,比如分组之后的子查询
 | 
			
		||||
        static ConcurrentDictionary<Type, MethodInfo> _dicSelectMethodToSql = new ConcurrentDictionary<Type, MethodInfo>();
 | 
			
		||||
        public string ExpressionLambdaToSql(Expression exp, ExpTSC tsc)
 | 
			
		||||
        {
 | 
			
		||||
            if (exp == null) return "";
 | 
			
		||||
@@ -1161,16 +1162,16 @@ namespace FreeSql.Internal
 | 
			
		||||
                                                    if (mn == 0) fsqlManyWhereExp = tmpExp;
 | 
			
		||||
                                                    else fsqlManyWhereExp = Expression.AndAlso(fsqlManyWhereExp, tmpExp);
 | 
			
		||||
                                                }
 | 
			
		||||
                                                fsqltables.Add(new SelectTableInfo { Alias = manySubSelectWhereParam.Name, Parameter = manySubSelectWhereParam, Table = manyTb, Type = SelectTableInfoType.Parent });
 | 
			
		||||
                                                fsqlWhere.Invoke(fsql, new object[] { Expression.Lambda(fsqlManyWhereExp, fsqlWhereParam) });
 | 
			
		||||
                                                var sql2 = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { "1" })?.ToString();
 | 
			
		||||
                                                if (string.IsNullOrEmpty(sql2) == false)
 | 
			
		||||
                                                    manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectWhereSql, Expression.Constant($"exists({sql2.Replace(" \r\n", " \r\n    ")})"), Expression.Constant(null));
 | 
			
		||||
                                                MethodInfo manySubSelectAggMethod = null;
 | 
			
		||||
                                                switch (exp3.Method.Name) //https://github.com/dotnetcore/FreeSql/issues/362
 | 
			
		||||
                                                {
 | 
			
		||||
                                                    case "Any":
 | 
			
		||||
                                                    case "Count":
 | 
			
		||||
                                                        fsqltables.Add(new SelectTableInfo { Alias = manySubSelectWhereParam.Name, Parameter = manySubSelectWhereParam, Table = manyTb, Type = SelectTableInfoType.Parent });
 | 
			
		||||
                                                        fsqlWhere.Invoke(fsql, new object[] { Expression.Lambda(fsqlManyWhereExp, fsqlWhereParam) });
 | 
			
		||||
                                                        var sql2 = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { "1" })?.ToString();
 | 
			
		||||
                                                        if (string.IsNullOrEmpty(sql2) == false)
 | 
			
		||||
                                                            manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectWhereSql, Expression.Constant($"exists({sql2.Replace(" \r\n", " \r\n    ")})"), Expression.Constant(null));
 | 
			
		||||
                                                        manySubSelectAggMethod = _dicExpressionLambdaToSqlAsSelectAggMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, _ => new ConcurrentDictionary<string, MethodInfo>()).GetOrAdd(exp3.Method.Name, exp3MethodName =>
 | 
			
		||||
                                                            typeof(ISelect0<,>).MakeGenericType(typeof(ISelect<>).MakeGenericType(parm123Ref.RefMiddleEntityType), parm123Ref.RefMiddleEntityType).GetMethod(exp3MethodName, new Type[0]));
 | 
			
		||||
                                                        manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectAggMethod);
 | 
			
		||||
@@ -1182,7 +1183,28 @@ namespace FreeSql.Internal
 | 
			
		||||
                                                    case "ToList":
 | 
			
		||||
                                                    case "ToOne":
 | 
			
		||||
                                                    case "First":
 | 
			
		||||
                                                        throw new ArgumentException($"ManyToMany 导航属性 .AsSelect() 暂时不可用于 Sum/Avg/Max/Min/First/ToOne/ToList 方法");
 | 
			
		||||
                                                        //解析:string.Join(",", w.Roles.AsSelect().ToList(b => b.RoleName)
 | 
			
		||||
                                                        var exp3Args0 = (exp3.Arguments[0] as UnaryExpression)?.Operand as LambdaExpression;
 | 
			
		||||
                                                        manySubSelectAggMethod = _dicSelectMethodToSql.GetOrAdd(fsqlType, fsqlType2 =>
 | 
			
		||||
                                                            fsqlType2.GetMethods().Where(a => a.Name == "ToSql" && a.GetParameters().Length == 2 && a.GetParameters()[1].ParameterType == typeof(FieldAliasOptions) && a.GetGenericArguments().Length == 1).FirstOrDefault());
 | 
			
		||||
                                                        if (manySubSelectAggMethod == null || exp3Args0 == null) throw new ArgumentException($"ManyToMany 导航属性 .AsSelect() 暂时不可用于 Sum/Avg/Max/Min/First/ToOne/ToList 方法");
 | 
			
		||||
                                                        manySubSelectAggMethod = manySubSelectAggMethod.MakeGenericMethod(exp3Args0.ReturnType);
 | 
			
		||||
                                                        var fsqls0p = fsql as Select0Provider;
 | 
			
		||||
                                                        var fsqls0pWhere = fsqls0p._where.ToString();
 | 
			
		||||
                                                        fsqls0p._where.Clear();
 | 
			
		||||
                                                        var fsqltablesLast = new SelectTableInfo { Alias = manySubSelectWhereParam.Name, Parameter = manySubSelectWhereParam, Table = manyTb, Type = SelectTableInfoType.InnerJoin };
 | 
			
		||||
                                                        fsqltables.Add(fsqltablesLast);
 | 
			
		||||
                                                        fsqlWhere.Invoke(fsql, new object[] { Expression.Lambda(fsqlManyWhereExp, fsqlWhereParam) });
 | 
			
		||||
                                                        fsqltablesLast.NavigateCondition = fsqls0p._where.ToString();
 | 
			
		||||
                                                        if (fsqltablesLast.NavigateCondition.StartsWith(" AND (")) fsqltablesLast.NavigateCondition = fsqltablesLast.NavigateCondition.Substring(6, fsqltablesLast.NavigateCondition.Length - 7);
 | 
			
		||||
                                                        fsqls0p._where.Clear().Append(fsqls0pWhere);
 | 
			
		||||
                                                        var tsc3 = tsc.CloneDisableDiyParse();
 | 
			
		||||
                                                        tsc3._tables = tsc._tables.ToList();
 | 
			
		||||
                                                        var where2 = ExpressionLambdaToSql(Expression.Lambda(manySubSelectWhereExp, manySubSelectWhereParam), tsc3);
 | 
			
		||||
                                                        if (string.IsNullOrEmpty(where2) == false) fsqls0p._where.Append(" AND (").Append(where2).Append(")");
 | 
			
		||||
                                                        var sql3 = manySubSelectAggMethod.Invoke(fsql, new object[] { exp3Args0, FieldAliasOptions.AsProperty }) as string;
 | 
			
		||||
                                                        asSelectBefores.Clear();
 | 
			
		||||
                                                        return $"({sql3.Replace(" \r\n", " \r\n    ")})";
 | 
			
		||||
                                                }
 | 
			
		||||
                                                asSelectBefores.Clear();
 | 
			
		||||
                                                return ExpressionLambdaToSql(manySubSelectExpBoy, tsc);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user