diff --git a/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index 74f0aa64..051898f8 100644 --- a/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -196,6 +196,22 @@ namespace FreeSql.Tests.MySql { var count = select.Where(a => 1 == 1).Count(); Assert.False(select.Where(a => 1 == 2).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); + + var sql2222 = select.Where(a => + select.Where(b => b.Id == a.Id && + select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id) + .Offset(a.Id) + .Any() + ).Any(c => c.Id == a.Id + 10) + ); + var sql2222Tolist = sql2222.ToList(); + + var collectionSelect = select.Where(a => + a.Type.Guid == a.TestTypeInfoGuid && + a.Type.Parent.Id == a.Type.ParentId && + a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id) + ); + collectionSelect.ToList(); } [Fact] public void Count() { diff --git a/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index ecb04ba4..8b847983 100644 --- a/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -70,6 +70,22 @@ namespace FreeSql.Tests.Oracle { var count = select.Where(a => 1 == 1).Count(); Assert.False(select.Where(a => 1 == 2).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); + + var sql2222 = select.Where(a => + select.Where(b => b.Id == a.Id && + select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id) + .Offset(a.Id) + .Any() + ).Any(c => c.Id == a.Id + 10) + ); + var sql2222Tolist = sql2222.ToList(); + + var collectionSelect = select.Where(a => + a.Type.Guid == a.TestTypeInfoGuid && + a.Type.Parent.Id == a.Type.ParentId && + a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id) + ); + collectionSelect.ToList(); } [Fact] public void Count() { diff --git a/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 3173de2d..d72fecb2 100644 --- a/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -138,6 +138,22 @@ namespace FreeSql.Tests.PostgreSQL { var count = select.Where(a => 1 == 1).Count(); Assert.False(select.Where(a => 1 == 2).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); + + var sql2222 = select.Where(a => + select.Where(b => b.Id == a.Id && + select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id) + .Offset(a.Id) + .Any() + ).Any(c => c.Id == a.Id + 10) + ); + var sql2222Tolist = sql2222.ToList(); + + var collectionSelect = select.Where(a => + a.Type.Guid == a.TestTypeInfoGuid && + a.Type.Parent.Id == a.Type.ParentId && + a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id) + ); + collectionSelect.ToList(); } [Fact] public void Count() { diff --git a/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index c9728c61..eb0dbc92 100644 --- a/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -71,6 +71,22 @@ namespace FreeSql.Tests.SqlServer { var count = select.Where(a => 1 == 1).Count(); Assert.False(select.Where(a => 1 == 2).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); + + var sql2222 = select.Where(a => + select.Where(b => b.Id == a.Id && + select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id) + .Offset(a.Id) + .Any() + ).Any(c => c.Id == a.Id + 10) + ); + var sql2222Tolist = sql2222.ToList(); + + var collectionSelect = select.Where(a => + a.Type.Guid == a.TestTypeInfoGuid && + a.Type.Parent.Id == a.Type.ParentId && + a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id) + ); + collectionSelect.ToList(); } [Fact] public void Count() { diff --git a/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index 02046f9e..3a4e9bdd 100644 --- a/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -102,6 +102,22 @@ namespace FreeSql.Tests.Sqlite { var count = select.Where(a => 1 == 1).Count(); Assert.False(select.Where(a => 1 == 2).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); + + var sql2222 = select.Where(a => + select.Where(b => b.Id == a.Id && + select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id) + .Offset(a.Id) + .Any() + ).Any(c => c.Id == a.Id + 10) + ); + var sql2222Tolist = sql2222.ToList(); + + var collectionSelect = select.Where(a => + a.Type.Guid == a.TestTypeInfoGuid && + a.Type.Parent.Id == a.Type.ParentId && + a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id) + ); + collectionSelect.ToList(); } [Fact] public void Count() { diff --git a/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/UnitTest1.cs index 00e942d9..da448bbb 100644 --- a/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/UnitTest1.cs @@ -27,15 +27,22 @@ namespace FreeSql.Tests { public virtual Order Order { get; set; } } - class NullAggreTestTable { - [Column(IsIdentity = true)] - public int Id { get; set; } - } - ISelect select => g.mysql.Select(); [Fact] public void Test1() { + var collSelect1 = g.mysql.Select().Where(a => + a.OrderDetails.AsSelect().Where(b => b.OrderId == a.OrderID).Any() + ); + + var collectionSelect = select.Where(a => + a.Type.Guid == a.TypeGuid && + a.Type.Parent.Id == a.Type.ParentId && + a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id) + ); + + + var order = g.mysql.Select().Where(a => a.OrderID == 1).ToOne(); //查询订单表 var orderDetail1 = order.OrderDetails; //第一次访问,查询数据库 var orderDetail2 = order.OrderDetails; //第二次访问,不查 @@ -182,6 +189,11 @@ namespace FreeSql.Tests { } } + class NullAggreTestTable { + [Column(IsIdentity = true)] + public int Id { get; set; } + } + [Table(Name = "xxx", SelectFilter = " a.id > 0")] class TestInfo { diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index f943ec40..39a52744 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -1,4 +1,5 @@ -锘縰sing System; +锘縰sing FreeSql; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; @@ -73,4 +74,17 @@ public static class FreeSqlGlobalExtensions { } return ret; } + + /// + /// 灏 IEnumable 杞垚 ISelect锛屼互渚夸娇鐢 FreeSql 鐨勬煡璇㈠姛鑳姐傛鏂规硶鐢ㄤ簬 Lambad 琛ㄨ揪寮忎腑锛屽揩閫熻繘琛岄泦鍚堝鑸殑鏌ヨ銆 + /// + /// + /// + /// + public static ISelect AsSelect(this IEnumerable that) where TEntity : class { + throw new NotImplementedException(); + } + public static ISelect AsSelect(this IEnumerable that, IFreeSql orm = null) where TEntity : class { + return orm?.Select(); + } } \ No newline at end of file diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 3b7b7885..dc544a73 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -1,5 +1,6 @@ 锘縰sing FreeSql.Internal.Model; using System; +using System.Collections; using System.Collections.Generic; using System.Data.Common; using System.Linq; @@ -236,12 +237,18 @@ namespace FreeSql.Internal { } if (callType.FullName.StartsWith("FreeSql.ISelect`")) { //瀛愯〃鏌ヨ if (exp3.Method.Name == "Any") { //exists + var anyArgs = exp3.Arguments; var exp3Stack = new Stack(); var exp3tmp = exp3.Object; + if (exp3tmp != null && anyArgs.Any()) + exp3Stack.Push(Expression.Call(exp3tmp, callType.GetMethod("Where", anyArgs.Select(a => a.Type).ToArray()), anyArgs.ToArray())); while (exp3tmp != null) { exp3Stack.Push(exp3tmp); switch (exp3tmp.NodeType) { - case ExpressionType.Call: exp3tmp = (exp3tmp as MethodCallExpression).Object; continue; + case ExpressionType.Call: + var exp3tmpCall = (exp3tmp as MethodCallExpression); + exp3tmp = exp3tmpCall.Object == null ? exp3tmpCall.Arguments.FirstOrDefault() : exp3tmpCall.Object; + continue; case ExpressionType.MemberAccess: exp3tmp = (exp3tmp as MemberExpression).Expression; continue; } break; @@ -253,7 +260,19 @@ namespace FreeSql.Internal { while (exp3Stack.Any()) { exp3tmp = exp3Stack.Pop(); if (exp3tmp.Type.FullName.StartsWith("FreeSql.ISelect`") && fsql == null) { - fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke(); + if (exp3tmp.NodeType == ExpressionType.Call) { + var exp3tmpCall = (exp3tmp as MethodCallExpression); + if (exp3tmpCall.Method.Name == "AsSelect" && exp3tmpCall.Object == null) { + var exp3tmpArg1Type = exp3tmpCall.Arguments.FirstOrDefault()?.Type; + if (exp3tmpArg1Type != null) { + var exp3tmpEleType = exp3tmpArg1Type.GetElementType() ?? exp3tmpArg1Type.GenericTypeArguments.FirstOrDefault(); + if (exp3tmpEleType != null) { + fsql = typeof(IFreeSql).GetMethod("Select", new Type[0]).MakeGenericMethod(exp3tmpEleType).Invoke(_common._orm, null); + } + } + } + } + if (fsql == null) fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke(); fsqlType = fsql?.GetType(); if (fsqlType == null) break; fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1); @@ -295,6 +314,12 @@ namespace FreeSql.Internal { } } } + var eleType = callType.GetElementType() ?? callType.GenericTypeArguments.FirstOrDefault(); + if (eleType != null && typeof(IEnumerable<>).MakeGenericType(eleType).IsAssignableFrom(callType)) { //闆嗗悎瀵艰埅灞炴у瓙鏌ヨ + if (exp3.Method.Name == "Any") { //exists + + } + } var other3Exp = ExpressionLambdaToSqlOther(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp; throw new Exception($"鏈疄鐜板嚱鏁拌〃杈惧紡 {exp3} 瑙f瀽");