From f76a46f3839fde95a20824fd3d8dbf62f20fb1f3 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Wed, 27 Apr 2022 20:27:24 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=20=E5=AF=BC=E8=88=AA?= =?UTF-8?q?=E9=9B=86=E5=90=88=E5=B1=9E=E6=80=A7=E8=AE=BF=E9=97=AE=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E7=9C=81=E7=95=A5=20AsSelect=EF=BC=9B#15=20#300=20#36?= =?UTF-8?q?2=20#509=20#698=20#644=20#903?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 56 +++- .../orm_vs/Properties/launchSettings.json | 8 + .../FreeSql.Extensions.Linq/ExprHelper.cs | 95 ------ .../MySqlConnector/Curd/MySqlSelectTest.cs | 181 ++++++++-- .../Dameng/Curd/DamengSelectTest.cs | 165 ++++++++-- .../Firebird/Curd/FirebirdSelectTest.cs | 165 ++++++++-- .../FreeSql.Tests/Linq/ExprHelperTest.cs | 16 +- .../MsAccess/Curd/MsAccessSelectTest.cs | 165 ++++++++-- .../MySql/Curd/MySqlSelectTest.cs | 181 ++++++++-- .../Oracle/Curd/OracleSelectTest.cs | 165 ++++++++-- .../PostgreSQL/Curd/PostgreSQLSelectTest.cs | 181 ++++++++-- .../SqlServer/Curd/SqlServerSelectTest.cs | 159 +++++++-- .../Sqlite/Curd/SqliteSelectTest.cs | 182 +++++++++-- .../Extensions/LambadaExpressionExtensions.cs | 68 +++- FreeSql/FreeSql.xml | 183 +++++++++++ FreeSql/Interface/IAop.cs | 5 +- FreeSql/Internal/CommonExpression.cs | 309 +++++++++++++++++- FreeSql/Internal/UtilsExpressionTree.cs | 1 + README.md | 4 +- README.zh-CN.md | 4 +- 20 files changed, 1947 insertions(+), 346 deletions(-) create mode 100644 Examples/orm_vs/Properties/launchSettings.json delete mode 100644 Extensions/FreeSql.Extensions.Linq/ExprHelper.cs diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index dda3e9bb..71f76025 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -23,7 +23,7 @@ using System.Threading.Tasks; namespace base_entity { - class Program + static class Program { class TestConfig { @@ -196,6 +196,17 @@ namespace base_entity fsql.UseJsonMap(); + //var txt1 = fsql.Ado.Query<(string, string)>("select '꧁꫞꯭丑小鸭꫞꧂', '123123中国人' from dual"); + + fsql.Insert(new Order { ShippingAddress = "'꧁꫞꯭丑小鸭꫞꧂'" }).ExecuteAffrows(); + fsql.Insert(new Order { ShippingAddress = "'123123中国人'" }).ExecuteAffrows(); + var lst1 = fsql.Select().ToList(); + + var lst2 = fsql.Select().ToListIgnore(a => new + { + a.ShippingAddress + }); + fsql.Delete().Where("1=1").ExecuteAffrows(); fsql.Insert(new[] { @@ -794,5 +805,48 @@ namespace base_entity Console.WriteLine("按任意键结束。。。"); Console.ReadKey(); } + + public static List ToListIgnore(this ISelect that, Expression> selector) + { + if (selector == null) return that.ToList(); + var s0p = that as Select0Provider; + var tb = s0p._tables[0]; + var parmExp = tb.Parameter ?? Expression.Parameter(tb.Table.Type, tb.Alias); + var initExps = tb.Table.Columns.Values + .Where(a => a.Attribute.IsIgnore == false) + .Select(a => new + { + exp = Expression.Bind(tb.Table.Properties[a.CsName], Expression.MakeMemberAccess(parmExp, tb.Table.Properties[a.CsName])), + ignored = TestMemberExpressionVisitor.IsExists(selector, Expression.MakeMemberAccess(parmExp, tb.Table.Properties[a.CsName])) + }) + .Where(a => a.ignored == false) + .Select(a => a.exp) + .ToArray(); + var lambda = Expression.Lambda>( + Expression.MemberInit( + Expression.New(tb.Table.Type), + initExps + ), + parmExp + ); + return that.ToList(lambda); + } + class TestMemberExpressionVisitor : ExpressionVisitor + { + public string MemberExpString; + public bool Result { get; private set; } + + public static bool IsExists(Expression selector, Expression memberExp) + { + var visitor = new TestMemberExpressionVisitor { MemberExpString = memberExp.ToString() }; + visitor.Visit(selector); + return visitor.Result; + } + protected override Expression VisitMember(MemberExpression node) + { + if (!Result && node.ToString() == MemberExpString) Result = true; + return node; + } + } } } diff --git a/Examples/orm_vs/Properties/launchSettings.json b/Examples/orm_vs/Properties/launchSettings.json new file mode 100644 index 00000000..33504c94 --- /dev/null +++ b/Examples/orm_vs/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WSL": { + "commandName": "WSL2", + "distributionName": "" + } + } +} \ No newline at end of file diff --git a/Extensions/FreeSql.Extensions.Linq/ExprHelper.cs b/Extensions/FreeSql.Extensions.Linq/ExprHelper.cs deleted file mode 100644 index 75d2e5aa..00000000 --- a/Extensions/FreeSql.Extensions.Linq/ExprHelper.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Linq.Expressions; -using System.Linq; -using System.Reflection; - -namespace FreeSql.Extensions.Linq -{ - public static class ExprHelper - { - public static object GetConstExprValue(this Expression exp) - { - if (exp.IsParameter()) return null; - - var expStack = new Stack(); - var exp2 = exp; - while (true) - { - switch (exp2?.NodeType) - { - case ExpressionType.Constant: - expStack.Push(exp2); - break; - case ExpressionType.MemberAccess: - expStack.Push(exp2); - exp2 = (exp2 as MemberExpression).Expression; - if (exp2 == null) break; - continue; - case ExpressionType.Call: - return Expression.Lambda(exp).Compile().DynamicInvoke(); - case ExpressionType.TypeAs: - case ExpressionType.Convert: - var oper2 = (exp2 as UnaryExpression).Operand; - if (oper2.NodeType == ExpressionType.Parameter) - { - var oper2Parm = oper2 as ParameterExpression; - expStack.Push(exp2.Type.IsAbstract || exp2.Type.IsInterface ? oper2Parm : Expression.Parameter(exp2.Type, oper2Parm.Name)); - } - else - expStack.Push(oper2); - break; - } - break; - } - object firstValue = null; - switch (expStack.First().NodeType) - { - case ExpressionType.Constant: - var expStackFirst = expStack.Pop() as ConstantExpression; - firstValue = expStackFirst?.Value; - break; - case ExpressionType.MemberAccess: - var expStackFirstMem = expStack.First() as MemberExpression; - if (expStackFirstMem.Expression?.NodeType == ExpressionType.Constant) - firstValue = (expStackFirstMem.Expression as ConstantExpression)?.Value; - else - return Expression.Lambda(exp).Compile().DynamicInvoke(); - break; - } - while (expStack.Any()) - { - var expStackItem = expStack.Pop(); - switch (expStackItem.NodeType) - { - case ExpressionType.MemberAccess: - var memExp = expStackItem as MemberExpression; - if (memExp.Member.MemberType == MemberTypes.Property) - firstValue = ((PropertyInfo)memExp.Member).GetValue(firstValue, null); - else if (memExp.Member.MemberType == MemberTypes.Field) - firstValue = ((FieldInfo)memExp.Member).GetValue(firstValue); - break; - } - } - return firstValue; - } - - public static bool IsParameter(this Expression exp) - { - var test = new TestParameterExpressionVisitor(); - test.Visit(exp); - return test.Result; - } - internal class TestParameterExpressionVisitor : ExpressionVisitor - { - public bool Result { get; private set; } - - protected override Expression VisitParameter(ParameterExpression node) - { - if (!Result) Result = true; - return node; - } - } - } -} diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs index 1874f482..05a755db 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -91,35 +91,166 @@ namespace FreeSql.Tests.MySqlConnector [Fact] public void AsSelect() { + var fsql = g.mysql; + //OneToOne、ManyToOne - var t0 = g.mysql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 - //FROM `Tag` a - //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` - //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` - //WHERE (a__Parent__Parent.`Name` = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` +WHERE (a__Parent__Parent.`Name` = '粤语')", t0); //OneToMany - var t1 = g.mysql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` - //FROM `Tag` a - //WHERE (exists(SELECT 1 - // FROM `Tag` t - // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` - // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` +FROM `Tag` a +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) + limit 0,1))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` +FROM `Tag` a +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` +FROM `Tag` a +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (((a.`Name`) in (SELECT t.`Name` as1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10))))", t15); + //ManyToMany - var t2 = g.mysql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` - //FROM `Song` a - //WHERE(exists(SELECT 1 - // FROM `Song_tag` Mt_Ms - // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 - // FROM `Tag` t - // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` +FROM `Song` a +WHERE (exists(SELECT 1 + FROM `Song_tag` Mt_Ms + WHERE (Mt_Ms.`Song_id` = a.`Id`) AND (exists(SELECT 1 + FROM `Tag` t + WHERE (t.`Name` = '国语') AND (t.`Id` = Mt_Ms.`Tag_id`) + limit 0,1)) + limit 0,1))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` +FROM `Song` a +WHERE (exists(SELECT 1 + FROM `Tag` t + WHERE (exists(SELECT 1 + FROM `Song_tag` Mt_Ma + WHERE (Mt_Ma.`Tag_id` = t.`Id`) AND (Mt_Ma.`Song_id` = a.`Id`) + limit 0,1)) AND (t.`Name` = '国语') + limit 0,1))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` +FROM `Song` a +WHERE (exists(SELECT 1 + FROM `Tag` t + WHERE (exists(SELECT 1 + FROM `Song_tag` Mt_Ma + WHERE (Mt_Ma.`Tag_id` = t.`Id`) AND (Mt_Ma.`Song_id` = a.`Id`) + limit 0,1)) AND (t.`Name` = '国语') + limit 0,1))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Song` s + WHERE (exists(SELECT 1 + FROM `Song_tag` Ms_Ma__Parent + WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`) + limit 0,1)) AND (s.`Title` = '中国人') + limit 0,1))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Song` s + WHERE (exists(SELECT 1 + FROM `Song_tag` Ms_Ma__Parent + WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`) + limit 0,1)) AND (s.`Title` = '中国人') + limit 0,1))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (((a.`Name`) in (SELECT s.`Title` as1 + FROM `Song` s + WHERE (exists(SELECT 1 + FROM `Song_tag` Ms_Ma__Parent + WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`) + limit 0,1)) AND (s.`Title` = '中国人'))))", t25); + + + var t3 = fsql.Select().ToList(r => new + { + r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs index 07867836..c28f4a05 100644 --- a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -83,35 +83,150 @@ namespace FreeSql.Tests.Dameng [Fact] public void AsSelect() { + var fsql = g.dameng; + //OneToOne、ManyToOne - var t0 = g.dameng.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 - //FROM `Tag` a - //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` - //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` - //WHERE (a__Parent__Parent.`Name` = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +LEFT JOIN ""TAG"" a__Parent__Parent ON a__Parent__Parent.""ID"" = a__Parent.""PARENT_ID"" +WHERE (a__Parent__Parent.""NAME"" = '粤语')", t0); //OneToMany - var t1 = g.dameng.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` - //FROM `Tag` a - //WHERE (exists(SELECT 1 - // FROM `Tag` t - // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` - // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t__Parent.""ID"" = 10) AND (t.""PARENT_ID"" = a.""ID"")))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a.""ID"") AND (t__Parent.""ID"" = 10)))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10)))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a.""ID"") AND (t__Parent.""ID"" = 10)))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10)))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (((a.""NAME"") in (SELECT t.""NAME"" as1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10))))", t15); + //ManyToMany - var t2 = g.dameng.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` - //FROM `Song` a - //WHERE(exists(SELECT 1 - // FROM `Song_tag` Mt_Ms - // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 - // FROM `Tag` t - // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Mt_Ms + WHERE (Mt_Ms.""SONG_ID"" = a.""ID"") AND (exists(SELECT 1 + FROM ""TAG"" t + WHERE (t.""NAME"" = '国语') AND (t.""ID"" = Mt_Ms.""TAG_ID"")))))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Mt_Ma + WHERE (Mt_Ma.""TAG_ID"" = t.""ID"") AND (Mt_Ma.""SONG_ID"" = a.""ID""))) AND (t.""NAME"" = '国语')))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Mt_Ma + WHERE (Mt_Ma.""TAG_ID"" = t.""ID"") AND (Mt_Ma.""SONG_ID"" = a.""ID""))) AND (t.""NAME"" = '国语')))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""SONG"" s + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人')))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""SONG"" s + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人')))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (((a.""NAME"") in (SELECT s.""TITLE"" as1 + FROM ""SONG"" s + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人'))))", t25); + + + var t3 = fsql.Select().ToList(r => new + { + r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs index c06dc6a9..9541ea13 100644 --- a/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -83,35 +83,150 @@ namespace FreeSql.Tests.Firebird [Fact] public void AsSelect() { + var fsql = g.firebird; + //OneToOne、ManyToOne - var t0 = g.firebird.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 - //FROM `Tag` a - //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` - //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` - //WHERE (a__Parent__Parent.`Name` = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +LEFT JOIN ""TAG"" a__Parent__Parent ON a__Parent__Parent.""ID"" = a__Parent.""PARENT_ID"" +WHERE (a__Parent__Parent.""NAME"" = '粤语')", t0); //OneToMany - var t1 = g.firebird.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` - //FROM `Tag` a - //WHERE (exists(SELECT 1 - // FROM `Tag` t - // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` - // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t__Parent.""ID"" = 10) AND (t.""PARENT_ID"" = a.""ID"")))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a.""ID"") AND (t__Parent.""ID"" = 10)))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10)))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a.""ID"") AND (t__Parent.""ID"" = 10)))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10)))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (((a.""NAME"") in (SELECT t.""NAME"" as1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10))))", t15); + //ManyToMany - var t2 = g.firebird.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` - //FROM `Song` a - //WHERE(exists(SELECT 1 - // FROM `Song_tag` Mt_Ms - // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 - // FROM `Tag` t - // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG_TAG"" Mt_Ms + WHERE (Mt_Ms.""SONG_ID"" = a.""ID"") AND (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + WHERE (t.""NAME"" = '国语') AND (t.""ID"" = Mt_Ms.""TAG_ID"")))))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG_TAG"" Mt_Ma + WHERE (Mt_Ma.""TAG_ID"" = t.""ID"") AND (Mt_Ma.""SONG_ID"" = a.""ID""))) AND (t.""NAME"" = '国语')))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT FIRST 1 1 + FROM ""TAG"" t + WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG_TAG"" Mt_Ma + WHERE (Mt_Ma.""TAG_ID"" = t.""ID"") AND (Mt_Ma.""SONG_ID"" = a.""ID""))) AND (t.""NAME"" = '国语')))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG"" s + WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人')))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG"" s + WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人')))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (((a.""NAME"") in (SELECT s.""TITLE"" as1 + FROM ""SONG"" s + WHERE (exists(SELECT FIRST 1 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人'))))", t25); + + + var t3 = fsql.Select().ToList(r => new + { + r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/Linq/ExprHelperTest.cs b/FreeSql.Tests/FreeSql.Tests/Linq/ExprHelperTest.cs index a302b81f..eb479490 100644 --- a/FreeSql.Tests/FreeSql.Tests/Linq/ExprHelperTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Linq/ExprHelperTest.cs @@ -26,16 +26,16 @@ namespace FreeSql.Tests.Linq [Fact] public void GetConstExprValue() { - Assert.Equal(-1, ExprHelper.GetConstExprValue(Expression.Constant(-1))); - Assert.Equal(-2, ExprHelper.GetConstExprValue(Expression.Constant(-2))); - Assert.Equal(0, ExprHelper.GetConstExprValue(Expression.Constant(0))); - Assert.Equal(1, ExprHelper.GetConstExprValue(Expression.Constant(1))); - Assert.Equal(2, ExprHelper.GetConstExprValue(Expression.Constant(2))); + Assert.Equal(-1, Expression.Constant(-1).GetConstExprValue()); + Assert.Equal(-2, Expression.Constant(-2).GetConstExprValue()); + Assert.Equal(0, Expression.Constant(0).GetConstExprValue()); + Assert.Equal(1, Expression.Constant(1).GetConstExprValue()); + Assert.Equal(2, Expression.Constant(2).GetConstExprValue()); var arr = new[] { -1, -2, 0, 1, 2 }; for (var a = 0; a < arr.Length; a++) { - Assert.Equal(arr[a], ExprHelper.GetConstExprValue(Expression.Constant(arr[a]))); + Assert.Equal(arr[a], Expression.Constant(arr[a]).GetConstExprValue()); } var arritems = new[] @@ -48,8 +48,8 @@ namespace FreeSql.Tests.Linq }; for (var a = 0; a < arr.Length; a++) { - Assert.Equal(arritems[a].Prop, ExprHelper.GetConstExprValue(Expression.Constant(arritems[a].Prop))); - Assert.Equal(arritems[a].Field, ExprHelper.GetConstExprValue(Expression.Constant(arritems[a].Field))); + Assert.Equal(arritems[a].Prop, Expression.Constant(arritems[a].Prop).GetConstExprValue()); + Assert.Equal(arritems[a].Field, Expression.Constant(arritems[a].Field).GetConstExprValue()); } } diff --git a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs index 6b720747..d4702afb 100644 --- a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -72,35 +72,150 @@ namespace FreeSql.Tests.MsAccess [Fact] public void AsSelect() { + var fsql = g.msaccess; + //OneToOne、ManyToOne - var t0 = g.msaccess.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 - //FROM [Tag] a - //LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] - //LEFT JOIN [Tag] a__Parent__Parent ON a__Parent__Parent.[Id] = a__Parent.[Parent_id] - //WHERE (a__Parent__Parent.[Name] = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as as3, a__Parent.[Parent_id] as as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as as7, a.[Name] as as8 +FROM ([Tag] a +LEFT JOIN [Tag] a__Parent ON (a__Parent.[Id] = a.[Parent_id])) +LEFT JOIN [Tag] a__Parent__Parent ON (a__Parent__Parent.[Id] = a__Parent.[Parent_id]) +WHERE (a__Parent__Parent.[Name] = '粤语')", t0); //OneToMany - var t1 = g.msaccess.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] - //FROM [Tag] a - //WHERE (exists(SELECT 1 - // FROM [Tag] t - // LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] - // WHERE (t__Parent.[Id] = 10) AND (t.[Parent_id] = a.[Id]) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] +FROM [Tag] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON (t__Parent.[Id] = t.[Parent_id]) + WHERE (t__Parent.[Id] = 10) AND (t.[Parent_id] = a.[Id])))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] +FROM [Tag] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON (t__Parent.[Id] = t.[Parent_id]) + WHERE (t.[Parent_id] = a.[Id]) AND (t__Parent.[Id] = 10)))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as as3, a__Parent.[Parent_id] as as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as as7, a.[Name] as as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON (a__Parent.[Id] = a.[Parent_id]) +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON (t__Parent.[Id] = t.[Parent_id]) + WHERE (t.[Parent_id] = a__Parent.[Id]) AND (t__Parent.[Id] = 10)))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] +FROM [Tag] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON (t__Parent.[Id] = t.[Parent_id]) + WHERE (t.[Parent_id] = a.[Id]) AND (t__Parent.[Id] = 10)))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as as3, a__Parent.[Parent_id] as as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as as7, a.[Name] as as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON (a__Parent.[Id] = a.[Parent_id]) +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON (t__Parent.[Id] = t.[Parent_id]) + WHERE (t.[Parent_id] = a__Parent.[Id]) AND (t__Parent.[Id] = 10)))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as as3, a__Parent.[Parent_id] as as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as as7, a.[Name] as as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON (a__Parent.[Id] = a.[Parent_id]) +WHERE (((a.[Name]) in (SELECT t.[Name] as as1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON (t__Parent.[Id] = t.[Parent_id]) + WHERE (t.[Parent_id] = a__Parent.[Id]) AND (t__Parent.[Id] = 10))))", t15); + //ManyToMany - var t2 = g.msaccess.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] - //FROM [Song] a - //WHERE(exists(SELECT 1 - // FROM [Song_tag] Mt_Ms - // WHERE(Mt_Ms.[Song_id] = a.[Id]) AND(exists(SELECT 1 - // FROM [Tag] t - // WHERE(t.[Name] = '国语') AND(t.[Id] = Mt_Ms.[Tag_id]) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] +FROM [Song] a +WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Mt_Ms + WHERE (Mt_Ms.[Song_id] = a.[Id]) AND (exists(SELECT TOP 1 1 + FROM [Tag] t + WHERE (t.[Name] = '国语') AND (t.[Id] = Mt_Ms.[Tag_id])))))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] +FROM [Song] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Mt_Ma + WHERE (Mt_Ma.[Tag_id] = t.[Id]) AND (Mt_Ma.[Song_id] = a.[Id]))) AND (t.[Name] = '国语')))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] +FROM [Song] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Mt_Ma + WHERE (Mt_Ma.[Tag_id] = t.[Id]) AND (Mt_Ma.[Song_id] = a.[Id]))) AND (t.[Name] = '国语')))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as as3, a__Parent.[Parent_id] as as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as as7, a.[Name] as as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON (a__Parent.[Id] = a.[Parent_id]) +WHERE (exists(SELECT TOP 1 1 + FROM [Song] s + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Ms_Ma__Parent + WHERE (Ms_Ma__Parent.[Song_id] = s.[Id]) AND (Ms_Ma__Parent.[Tag_id] = a__Parent.[Id]))) AND (s.[Title] = '中国人')))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as as3, a__Parent.[Parent_id] as as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as as7, a.[Name] as as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON (a__Parent.[Id] = a.[Parent_id]) +WHERE (exists(SELECT TOP 1 1 + FROM [Song] s + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Ms_Ma__Parent + WHERE (Ms_Ma__Parent.[Song_id] = s.[Id]) AND (Ms_Ma__Parent.[Tag_id] = a__Parent.[Id]))) AND (s.[Title] = '中国人')))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as as3, a__Parent.[Parent_id] as as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as as7, a.[Name] as as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON (a__Parent.[Id] = a.[Parent_id]) +WHERE (((a.[Name]) in (SELECT s.[Title] as as1 + FROM [Song] s + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Ms_Ma__Parent + WHERE (Ms_Ma__Parent.[Song_id] = s.[Id]) AND (Ms_Ma__Parent.[Tag_id] = a__Parent.[Id]))) AND (s.[Title] = '中国人'))))", t25); + + + var t3 = fsql.Select().First(r => new + { + r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index 6ef0c1f6..280f69d3 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using FreeSql.Internal.CommonProvider; using Newtonsoft.Json; using System; @@ -93,35 +93,166 @@ namespace FreeSql.Tests.MySql [Fact] public void AsSelect() { + var fsql = g.mysql; + //OneToOne、ManyToOne - var t0 = g.mysql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 - //FROM `Tag` a - //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` - //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` - //WHERE (a__Parent__Parent.`Name` = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` +WHERE (a__Parent__Parent.`Name` = '粤语')", t0); //OneToMany - var t1 = g.mysql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` - //FROM `Tag` a - //WHERE (exists(SELECT 1 - // FROM `Tag` t - // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` - // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` +FROM `Tag` a +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) + limit 0,1))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` +FROM `Tag` a +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` +FROM `Tag` a +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10) + limit 0,1))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (((a.`Name`) in (SELECT t.`Name` as1 + FROM `Tag` t + LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10))))", t15); + //ManyToMany - var t2 = g.mysql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` - //FROM `Song` a - //WHERE(exists(SELECT 1 - // FROM `Song_tag` Mt_Ms - // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 - // FROM `Tag` t - // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` +FROM `Song` a +WHERE (exists(SELECT 1 + FROM `Song_tag` Mt_Ms + WHERE (Mt_Ms.`Song_id` = a.`Id`) AND (exists(SELECT 1 + FROM `Tag` t + WHERE (t.`Name` = '国语') AND (t.`Id` = Mt_Ms.`Tag_id`) + limit 0,1)) + limit 0,1))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` +FROM `Song` a +WHERE (exists(SELECT 1 + FROM `Tag` t + WHERE (exists(SELECT 1 + FROM `Song_tag` Mt_Ma + WHERE (Mt_Ma.`Tag_id` = t.`Id`) AND (Mt_Ma.`Song_id` = a.`Id`) + limit 0,1)) AND (t.`Name` = '国语') + limit 0,1))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` +FROM `Song` a +WHERE (exists(SELECT 1 + FROM `Tag` t + WHERE (exists(SELECT 1 + FROM `Song_tag` Mt_Ma + WHERE (Mt_Ma.`Tag_id` = t.`Id`) AND (Mt_Ma.`Song_id` = a.`Id`) + limit 0,1)) AND (t.`Name` = '国语') + limit 0,1))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Song` s + WHERE (exists(SELECT 1 + FROM `Song_tag` Ms_Ma__Parent + WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`) + limit 0,1)) AND (s.`Title` = '中国人') + limit 0,1))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (exists(SELECT 1 + FROM `Song` s + WHERE (exists(SELECT 1 + FROM `Song_tag` Ms_Ma__Parent + WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`) + limit 0,1)) AND (s.`Title` = '中国人') + limit 0,1))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 +FROM `Tag` a +LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` +WHERE (((a.`Name`) in (SELECT s.`Title` as1 + FROM `Song` s + WHERE (exists(SELECT 1 + FROM `Song_tag` Ms_Ma__Parent + WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`) + limit 0,1)) AND (s.`Title` = '中国人'))))", t25); + + + var t3 = fsql.Select().ToList(r => new + { + r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index b75967ff..0ac06d24 100644 --- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -83,35 +83,150 @@ namespace FreeSql.Tests.Oracle [Fact] public void AsSelect() { + var fsql = g.oracle; + //OneToOne、ManyToOne - var t0 = g.oracle.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 - //FROM `Tag` a - //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` - //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` - //WHERE (a__Parent__Parent.`Name` = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +LEFT JOIN ""TAG"" a__Parent__Parent ON a__Parent__Parent.""ID"" = a__Parent.""PARENT_ID"" +WHERE (a__Parent__Parent.""NAME"" = '粤语')", t0); //OneToMany - var t1 = g.oracle.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` - //FROM `Tag` a - //WHERE (exists(SELECT 1 - // FROM `Tag` t - // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` - // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t__Parent.""ID"" = 10) AND (t.""PARENT_ID"" = a.""ID"")))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a.""ID"") AND (t__Parent.""ID"" = 10)))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10)))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a.""DDD"", a.""NAME"" +FROM ""TAG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a.""ID"") AND (t__Parent.""ID"" = 10)))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10)))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (((a.""NAME"") in (SELECT t.""NAME"" as1 + FROM ""TAG"" t + LEFT JOIN ""TAG"" t__Parent ON t__Parent.""ID"" = t.""PARENT_ID"" + WHERE (t.""PARENT_ID"" = a__Parent.""ID"") AND (t__Parent.""ID"" = 10))))", t15); + //ManyToMany - var t2 = g.oracle.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` - //FROM `Song` a - //WHERE(exists(SELECT 1 - // FROM `Song_tag` Mt_Ms - // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 - // FROM `Tag` t - // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Mt_Ms + WHERE (Mt_Ms.""SONG_ID"" = a.""ID"") AND (exists(SELECT 1 + FROM ""TAG"" t + WHERE (t.""NAME"" = '国语') AND (t.""ID"" = Mt_Ms.""TAG_ID"")))))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Mt_Ma + WHERE (Mt_Ma.""TAG_ID"" = t.""ID"") AND (Mt_Ma.""SONG_ID"" = a.""ID""))) AND (t.""NAME"" = '国语')))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""CREATE_TIME"", a.""IS_DELETED"", a.""TITLE"", a.""URL"" +FROM ""SONG"" a +WHERE (exists(SELECT 1 + FROM ""TAG"" t + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Mt_Ma + WHERE (Mt_Ma.""TAG_ID"" = t.""ID"") AND (Mt_Ma.""SONG_ID"" = a.""ID""))) AND (t.""NAME"" = '国语')))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""SONG"" s + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人')))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (exists(SELECT 1 + FROM ""SONG"" s + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人')))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.""ID"", a.""PARENT_ID"", a__Parent.""ID"" as3, a__Parent.""PARENT_ID"" as4, a__Parent.""DDD"", a__Parent.""NAME"", a.""DDD"" as7, a.""NAME"" as8 +FROM ""TAG"" a +LEFT JOIN ""TAG"" a__Parent ON a__Parent.""ID"" = a.""PARENT_ID"" +WHERE (((a.""NAME"") in (SELECT s.""TITLE"" as1 + FROM ""SONG"" s + WHERE (exists(SELECT 1 + FROM ""SONG_TAG"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""SONG_ID"" = s.""ID"") AND (Ms_Ma__Parent.""TAG_ID"" = a__Parent.""ID""))) AND (s.""TITLE"" = '中国人'))))", t25); + + + var t3 = fsql.Select().ToList(r => new + { + r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index b5df0468..590cd131 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using System; using System.Collections.Generic; using System.Linq; @@ -73,35 +73,166 @@ namespace FreeSql.Tests.PostgreSQL [Fact] public void AsSelect() { + var fsql = g.pgsql; + //OneToOne、ManyToOne - var t0 = g.pgsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 - //FROM `Tag` a - //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` - //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` - //WHERE (a__Parent__Parent.`Name` = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a__Parent.""id"" as3, a__Parent.""parent_id"" as4, a__Parent.""ddd"", a__Parent.""name"", a.""ddd"" as7, a.""name"" as8 +FROM ""tag"" a +LEFT JOIN ""tag"" a__Parent ON a__Parent.""id"" = a.""parent_id"" +LEFT JOIN ""tag"" a__Parent__Parent ON a__Parent__Parent.""id"" = a__Parent.""parent_id"" +WHERE (a__Parent__Parent.""name"" = '粤语')", t0); //OneToMany - var t1 = g.pgsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` - //FROM `Tag` a - //WHERE (exists(SELECT 1 - // FROM `Tag` t - // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` - // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a.""ddd"", a.""name"" +FROM ""tag"" a +WHERE (exists(SELECT 1 + FROM ""tag"" t + LEFT JOIN ""tag"" t__Parent ON t__Parent.""id"" = t.""parent_id"" + WHERE (t__Parent.""id"" = 10) AND (t.""parent_id"" = a.""id"") + limit 1))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a.""ddd"", a.""name"" +FROM ""tag"" a +WHERE (exists(SELECT 1 + FROM ""tag"" t + LEFT JOIN ""tag"" t__Parent ON t__Parent.""id"" = t.""parent_id"" + WHERE (t.""parent_id"" = a.""id"") AND (t__Parent.""id"" = 10) + limit 1))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a__Parent.""id"" as3, a__Parent.""parent_id"" as4, a__Parent.""ddd"", a__Parent.""name"", a.""ddd"" as7, a.""name"" as8 +FROM ""tag"" a +LEFT JOIN ""tag"" a__Parent ON a__Parent.""id"" = a.""parent_id"" +WHERE (exists(SELECT 1 + FROM ""tag"" t + LEFT JOIN ""tag"" t__Parent ON t__Parent.""id"" = t.""parent_id"" + WHERE (t.""parent_id"" = a__Parent.""id"") AND (t__Parent.""id"" = 10) + limit 1))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a.""ddd"", a.""name"" +FROM ""tag"" a +WHERE (exists(SELECT 1 + FROM ""tag"" t + LEFT JOIN ""tag"" t__Parent ON t__Parent.""id"" = t.""parent_id"" + WHERE (t.""parent_id"" = a.""id"") AND (t__Parent.""id"" = 10) + limit 1))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a__Parent.""id"" as3, a__Parent.""parent_id"" as4, a__Parent.""ddd"", a__Parent.""name"", a.""ddd"" as7, a.""name"" as8 +FROM ""tag"" a +LEFT JOIN ""tag"" a__Parent ON a__Parent.""id"" = a.""parent_id"" +WHERE (exists(SELECT 1 + FROM ""tag"" t + LEFT JOIN ""tag"" t__Parent ON t__Parent.""id"" = t.""parent_id"" + WHERE (t.""parent_id"" = a__Parent.""id"") AND (t__Parent.""id"" = 10) + limit 1))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a__Parent.""id"" as3, a__Parent.""parent_id"" as4, a__Parent.""ddd"", a__Parent.""name"", a.""ddd"" as7, a.""name"" as8 +FROM ""tag"" a +LEFT JOIN ""tag"" a__Parent ON a__Parent.""id"" = a.""parent_id"" +WHERE (((a.""name"") in (SELECT t.""name"" as1 + FROM ""tag"" t + LEFT JOIN ""tag"" t__Parent ON t__Parent.""id"" = t.""parent_id"" + WHERE (t.""parent_id"" = a__Parent.""id"") AND (t__Parent.""id"" = 10))))", t15); + //ManyToMany - var t2 = g.pgsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` - //FROM `Song` a - //WHERE(exists(SELECT 1 - // FROM `Song_tag` Mt_Ms - // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 - // FROM `Tag` t - // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""id"", a.""create_time"", a.""is_deleted"", a.""title"", a.""url"" +FROM ""song"" a +WHERE (exists(SELECT 1 + FROM ""song_tag"" Mt_Ms + WHERE (Mt_Ms.""song_id"" = a.""id"") AND (exists(SELECT 1 + FROM ""tag"" t + WHERE (t.""name"" = '国语') AND (t.""id"" = Mt_Ms.""tag_id"") + limit 1)) + limit 1))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""id"", a.""create_time"", a.""is_deleted"", a.""title"", a.""url"" +FROM ""song"" a +WHERE (exists(SELECT 1 + FROM ""tag"" t + WHERE (exists(SELECT 1 + FROM ""song_tag"" Mt_Ma + WHERE (Mt_Ma.""tag_id"" = t.""id"") AND (Mt_Ma.""song_id"" = a.""id"") + limit 1)) AND (t.""name"" = '国语') + limit 1))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.""id"", a.""create_time"", a.""is_deleted"", a.""title"", a.""url"" +FROM ""song"" a +WHERE (exists(SELECT 1 + FROM ""tag"" t + WHERE (exists(SELECT 1 + FROM ""song_tag"" Mt_Ma + WHERE (Mt_Ma.""tag_id"" = t.""id"") AND (Mt_Ma.""song_id"" = a.""id"") + limit 1)) AND (t.""name"" = '国语') + limit 1))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a__Parent.""id"" as3, a__Parent.""parent_id"" as4, a__Parent.""ddd"", a__Parent.""name"", a.""ddd"" as7, a.""name"" as8 +FROM ""tag"" a +LEFT JOIN ""tag"" a__Parent ON a__Parent.""id"" = a.""parent_id"" +WHERE (exists(SELECT 1 + FROM ""song"" s + WHERE (exists(SELECT 1 + FROM ""song_tag"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""song_id"" = s.""id"") AND (Ms_Ma__Parent.""tag_id"" = a__Parent.""id"") + limit 1)) AND (s.""title"" = '中国人') + limit 1))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a__Parent.""id"" as3, a__Parent.""parent_id"" as4, a__Parent.""ddd"", a__Parent.""name"", a.""ddd"" as7, a.""name"" as8 +FROM ""tag"" a +LEFT JOIN ""tag"" a__Parent ON a__Parent.""id"" = a.""parent_id"" +WHERE (exists(SELECT 1 + FROM ""song"" s + WHERE (exists(SELECT 1 + FROM ""song_tag"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""song_id"" = s.""id"") AND (Ms_Ma__Parent.""tag_id"" = a__Parent.""id"") + limit 1)) AND (s.""title"" = '中国人') + limit 1))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.""id"", a.""parent_id"", a__Parent.""id"" as3, a__Parent.""parent_id"" as4, a__Parent.""ddd"", a__Parent.""name"", a.""ddd"" as7, a.""name"" as8 +FROM ""tag"" a +LEFT JOIN ""tag"" a__Parent ON a__Parent.""id"" = a.""parent_id"" +WHERE (((a.""name"") in (SELECT s.""title"" as1 + FROM ""song"" s + WHERE (exists(SELECT 1 + FROM ""song_tag"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""song_id"" = s.""id"") AND (Ms_Ma__Parent.""tag_id"" = a__Parent.""id"") + limit 1)) AND (s.""title"" = '中国人'))))", t25); + + + var t3 = fsql.Select().ToList(r => new + { + r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index 2679f9c7..52a1742b 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using FreeSql.Tests.DataContext.SqlServer; using NetTaste; using System; @@ -83,40 +83,145 @@ namespace FreeSql.Tests.SqlServer [Fact] public void AsSelect() { + var fsql = g.sqlserver; + //OneToOne、ManyToOne - var t0 = g.sqlserver.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 - //FROM [Tag] a - //LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] - //LEFT JOIN [Tag] a__Parent__Parent ON a__Parent__Parent.[Id] = a__Parent.[Parent_id] - //WHERE (a__Parent__Parent.[Name] = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + //Assert.Equal(@"", t0); //OneToMany - var t1 = g.sqlserver.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] - //FROM [Tag] a - //WHERE (exists(SELECT 1 - // FROM [Tag] t - // LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] - // WHERE (t__Parent.[Id] = 10) AND (t.[Parent_id] = a.[Id]) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] +FROM [Tag] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] + WHERE (t__Parent.[Id] = 10) AND (t.[Parent_id] = a.[Id])))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] +FROM [Tag] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] + WHERE (t.[Parent_id] = a.[Id]) AND (t__Parent.[Id] = 10)))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] + WHERE (t.[Parent_id] = a__Parent.[Id]) AND (t__Parent.[Id] = 10)))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a.[Ddd], a.[Name] +FROM [Tag] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] + WHERE (t.[Parent_id] = a.[Id]) AND (t__Parent.[Id] = 10)))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] + WHERE (t.[Parent_id] = a__Parent.[Id]) AND (t__Parent.[Id] = 10)))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] +WHERE (((a.[Name]) in (SELECT t.[Name] as1 + FROM [Tag] t + LEFT JOIN [Tag] t__Parent ON t__Parent.[Id] = t.[Parent_id] + WHERE (t.[Parent_id] = a__Parent.[Id]) AND (t__Parent.[Id] = 10))))", t15); + //ManyToMany - var t2 = g.sqlserver.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] - //FROM [Song] a - //WHERE(exists(SELECT 1 - // FROM [Song_tag] Mt_Ms - // WHERE(Mt_Ms.[Song_id] = a.[Id]) AND(exists(SELECT 1 - // FROM [Tag] t - // WHERE(t.[Name] = '国语') AND(t.[Id] = Mt_Ms.[Tag_id]) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] +FROM [Song] a +WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Mt_Ms + WHERE (Mt_Ms.[Song_id] = a.[Id]) AND (exists(SELECT TOP 1 1 + FROM [Tag] t + WHERE (t.[Name] = N'国语') AND (t.[Id] = Mt_Ms.[Tag_id])))))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] +FROM [Song] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Mt_Ma + WHERE (Mt_Ma.[Tag_id] = t.[Id]) AND (Mt_Ma.[Song_id] = a.[Id]))) AND (t.[Name] = N'国语')))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Create_time], a.[Is_deleted], a.[Title], a.[Url] +FROM [Song] a +WHERE (exists(SELECT TOP 1 1 + FROM [Tag] t + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Mt_Ma + WHERE (Mt_Ma.[Tag_id] = t.[Id]) AND (Mt_Ma.[Song_id] = a.[Id]))) AND (t.[Name] = N'国语')))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] +WHERE (exists(SELECT TOP 1 1 + FROM [Song] s + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Ms_Ma__Parent + WHERE (Ms_Ma__Parent.[Song_id] = s.[Id]) AND (Ms_Ma__Parent.[Tag_id] = a__Parent.[Id]))) AND (s.[Title] = N'中国人')))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] +WHERE (exists(SELECT TOP 1 1 + FROM [Song] s + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Ms_Ma__Parent + WHERE (Ms_Ma__Parent.[Song_id] = s.[Id]) AND (Ms_Ma__Parent.[Tag_id] = a__Parent.[Id]))) AND (s.[Title] = N'中国人')))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.[Id], a.[Parent_id], a__Parent.[Id] as3, a__Parent.[Parent_id] as4, a__Parent.[Ddd], a__Parent.[Name], a.[Ddd] as7, a.[Name] as8 +FROM [Tag] a +LEFT JOIN [Tag] a__Parent ON a__Parent.[Id] = a.[Parent_id] +WHERE (((a.[Name]) in (SELECT s.[Title] as1 + FROM [Song] s + WHERE (exists(SELECT TOP 1 1 + FROM [Song_tag] Ms_Ma__Parent + WHERE (Ms_Ma__Parent.[Song_id] = s.[Id]) AND (Ms_Ma__Parent.[Tag_id] = a__Parent.[Id]))) AND (s.[Title] = N'中国人'))))", t25); - var t3 = g.sqlserver.Select().ToList(r => new + + var t3 = fsql.Select().ToList(r => new { r.Title, - count = r.Tags.AsSelect().Count() + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + + count = r.Tags.AsSelect().Count(), + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) }); } diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index 2d5ec8a6..6b832a26 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -1,4 +1,4 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using FreeSql.Internal.Model; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -81,45 +81,165 @@ namespace FreeSql.Tests.Sqlite [Fact] public void AsSelect() { + var fsql = g.sqlite; + //OneToOne、ManyToOne - var t0 = g.sqlite.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 - //FROM `Tag` a - //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` - //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` - //WHERE (a__Parent__Parent.`Name` = '粤语') + var t0 = fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + fsql.Select().Where(a => a.Parent.Parent.Name == "粤语").First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a__Parent.""Id"" as3, a__Parent.""Parent_id"" as4, a__Parent.""Ddd"", a__Parent.""Name"", a.""Ddd"" as7, a.""Name"" as8 +FROM ""Tag"" a +LEFT JOIN ""Tag"" a__Parent ON a__Parent.""Id"" = a.""Parent_id"" +LEFT JOIN ""Tag"" a__Parent__Parent ON a__Parent__Parent.""Id"" = a__Parent.""Parent_id"" +WHERE (a__Parent__Parent.""Name"" = '粤语')", t0); //OneToMany - var t1 = g.sqlite.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); - //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` - //FROM `Tag` a - //WHERE (exists(SELECT 1 - // FROM `Tag` t - // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` - // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) - // limit 0,1)) + var t1 = fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a.""Ddd"", a.""Name"" +FROM ""Tag"" a +WHERE (exists(SELECT 1 + FROM ""Tag"" t + LEFT JOIN ""Tag"" t__Parent ON t__Parent.""Id"" = t.""Parent_id"" + WHERE (t__Parent.""Id"" = 10) AND (t.""Parent_id"" = a.""Id"") + limit 0,1))", t1); + var t11 = fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a.""Ddd"", a.""Name"" +FROM ""Tag"" a +WHERE (exists(SELECT 1 + FROM ""Tag"" t + LEFT JOIN ""Tag"" t__Parent ON t__Parent.""Id"" = t.""Parent_id"" + WHERE (t.""Parent_id"" = a.""Id"") AND (t__Parent.""Id"" = 10) + limit 0,1))", t11); + var t12 = fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a__Parent.""Id"" as3, a__Parent.""Parent_id"" as4, a__Parent.""Ddd"", a__Parent.""Name"", a.""Ddd"" as7, a.""Name"" as8 +FROM ""Tag"" a +LEFT JOIN ""Tag"" a__Parent ON a__Parent.""Id"" = a.""Parent_id"" +WHERE (exists(SELECT 1 + FROM ""Tag"" t + LEFT JOIN ""Tag"" t__Parent ON t__Parent.""Id"" = t.""Parent_id"" + WHERE (t.""Parent_id"" = a__Parent.""Id"") AND (t__Parent.""Id"" = 10) + limit 0,1))", t12); + var t13 = fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a.""Ddd"", a.""Name"" +FROM ""Tag"" a +WHERE (exists(SELECT 1 + FROM ""Tag"" t + LEFT JOIN ""Tag"" t__Parent ON t__Parent.""Id"" = t.""Parent_id"" + WHERE (t.""Parent_id"" = a.""Id"") AND (t__Parent.""Id"" = 10) + limit 0,1))", t13); + var t14 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a__Parent.""Id"" as3, a__Parent.""Parent_id"" as4, a__Parent.""Ddd"", a__Parent.""Name"", a.""Ddd"" as7, a.""Name"" as8 +FROM ""Tag"" a +LEFT JOIN ""Tag"" a__Parent ON a__Parent.""Id"" = a.""Parent_id"" +WHERE (exists(SELECT 1 + FROM ""Tag"" t + LEFT JOIN ""Tag"" t__Parent ON t__Parent.""Id"" = t.""Parent_id"" + WHERE (t.""Parent_id"" = a__Parent.""Id"") AND (t__Parent.""Id"" = 10) + limit 0,1))", t14); + var t15 = fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql(); + fsql.Select().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a__Parent.""Id"" as3, a__Parent.""Parent_id"" as4, a__Parent.""Ddd"", a__Parent.""Name"", a.""Ddd"" as7, a.""Name"" as8 +FROM ""Tag"" a +LEFT JOIN ""Tag"" a__Parent ON a__Parent.""Id"" = a.""Parent_id"" +WHERE (((a.""Name"") in (SELECT t.""Name"" as1 + FROM ""Tag"" t + LEFT JOIN ""Tag"" t__Parent ON t__Parent.""Id"" = t.""Parent_id"" + WHERE (t.""Parent_id"" = a__Parent.""Id"") AND (t__Parent.""Id"" = 10))))", t15); + //ManyToMany - var t2 = g.sqlite.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); - //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` - //FROM `Song` a - //WHERE(exists(SELECT 1 - // FROM `Song_tag` Mt_Ms - // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 - // FROM `Tag` t - // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) - // limit 0, 1)) - // limit 0, 1)) + var t2 = fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Create_time"", a.""Is_deleted"", a.""Title"", a.""Url"" +FROM ""Song"" a +WHERE (exists(SELECT 1 + FROM ""Song_tag"" Mt_Ms + WHERE (Mt_Ms.""Song_id"" = a.""Id"") AND (exists(SELECT 1 + FROM ""Tag"" t + WHERE (t.""Name"" = '国语') AND (t.""Id"" = Mt_Ms.""Tag_id"") + limit 0,1)) + limit 0,1))", t2); + var t21 = fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql(); + fsql.Select().Where(s => s.Tags.Any(t => t.Name == "国语")).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Create_time"", a.""Is_deleted"", a.""Title"", a.""Url"" +FROM ""Song"" a +WHERE (exists(SELECT 1 + FROM ""Tag"" t + WHERE (exists(SELECT 1 + FROM ""Song_tag"" Mt_Ma + WHERE (Mt_Ma.""Tag_id"" = t.""Id"") AND (Mt_Ma.""Song_id"" = a.""Id"") + limit 0,1)) AND (t.""Name"" = '国语') + limit 0,1))", t21); + var t22 = fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql(); + fsql.Select().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Create_time"", a.""Is_deleted"", a.""Title"", a.""Url"" +FROM ""Song"" a +WHERE (exists(SELECT 1 + FROM ""Tag"" t + WHERE (exists(SELECT 1 + FROM ""Song_tag"" Mt_Ma + WHERE (Mt_Ma.""Tag_id"" = t.""Id"") AND (Mt_Ma.""Song_id"" = a.""Id"") + limit 0,1)) AND (t.""Name"" = '国语') + limit 0,1))", t22); + var t23 = fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a__Parent.""Id"" as3, a__Parent.""Parent_id"" as4, a__Parent.""Ddd"", a__Parent.""Name"", a.""Ddd"" as7, a.""Name"" as8 +FROM ""Tag"" a +LEFT JOIN ""Tag"" a__Parent ON a__Parent.""Id"" = a.""Parent_id"" +WHERE (exists(SELECT 1 + FROM ""Song"" s + WHERE (exists(SELECT 1 + FROM ""Song_tag"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""Song_id"" = s.""Id"") AND (Ms_Ma__Parent.""Tag_id"" = a__Parent.""Id"") + limit 0,1)) AND (s.""Title"" = '中国人') + limit 0,1))", t23); + var t24 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a__Parent.""Id"" as3, a__Parent.""Parent_id"" as4, a__Parent.""Ddd"", a__Parent.""Name"", a.""Ddd"" as7, a.""Name"" as8 +FROM ""Tag"" a +LEFT JOIN ""Tag"" a__Parent ON a__Parent.""Id"" = a.""Parent_id"" +WHERE (exists(SELECT 1 + FROM ""Song"" s + WHERE (exists(SELECT 1 + FROM ""Song_tag"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""Song_id"" = s.""Id"") AND (Ms_Ma__Parent.""Tag_id"" = a__Parent.""Id"") + limit 0,1)) AND (s.""Title"" = '中国人') + limit 0,1))", t24); + var t25 = fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql(); + fsql.Select().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First(); + Assert.Equal(@"SELECT a.""Id"", a.""Parent_id"", a__Parent.""Id"" as3, a__Parent.""Parent_id"" as4, a__Parent.""Ddd"", a__Parent.""Name"", a.""Ddd"" as7, a.""Name"" as8 +FROM ""Tag"" a +LEFT JOIN ""Tag"" a__Parent ON a__Parent.""Id"" = a.""Parent_id"" +WHERE (((a.""Name"") in (SELECT s.""Title"" as1 + FROM ""Song"" s + WHERE (exists(SELECT 1 + FROM ""Song_tag"" Ms_Ma__Parent + WHERE (Ms_Ma__Parent.""Song_id"" = s.""Id"") AND (Ms_Ma__Parent.""Tag_id"" = a__Parent.""Id"") + limit 0,1)) AND (s.""Title"" = '中国人'))))", t25); - var t3 = g.sqlite.Select().ToList(r => new + + var t3 = fsql.Select().ToList(r => new { r.Title, + c2 = r.Tags.Count, + c3 = r.Tags.Count(), + c4 = r.Tags.Count(tag => tag.Id > 0), + s1 = r.Tags.Sum(b => b.Id + 0), + a1 = r.Tags.Average(b => b.Id + 1), + m1 = r.Tags.Max(b => b.Id + 2), + m2 = r.Tags.Min(b => b.Id + 3), + f1 = r.Tags.Select(b => b.Name).First(), + count = r.Tags.AsSelect().Count(), - //sum = r.Tags.AsSelect().Sum(b => b.Id + 0), - //avg = r.Tags.AsSelect().Avg(b => b.Id + 1), - //max = r.Tags.AsSelect().Max(b => b.Id + 2), - //min = r.Tags.AsSelect().Min(b => b.Id + 3), - //first = r.Tags.AsSelect().First(b => b.Name) + sum = r.Tags.AsSelect().Sum(b => b.Id + 0), + avg = r.Tags.AsSelect().Avg(b => b.Id + 1), + max = r.Tags.AsSelect().Max(b => b.Id + 2), + min = r.Tags.AsSelect().Min(b => b.Id + 3), + first = r.Tags.AsSelect().First(b => b.Name) }); } diff --git a/FreeSql/Extensions/LambadaExpressionExtensions.cs b/FreeSql/Extensions/LambadaExpressionExtensions.cs index 3ed0f207..61a6eb5a 100644 --- a/FreeSql/Extensions/LambadaExpressionExtensions.cs +++ b/FreeSql/Extensions/LambadaExpressionExtensions.cs @@ -227,7 +227,7 @@ namespace System.Linq.Expressions public static Expression> Not(this Expression> exp, bool condition = true) => (Expression>)InternalNotExpression(condition, exp); #endregion - internal static bool IsParameter(this Expression exp) + public static bool IsParameter(this Expression exp) { var test = new TestParameterExpressionVisitor(); test.Visit(exp); @@ -258,6 +258,72 @@ namespace System.Linq.Expressions toListArgs0Out = null; return false; } + + public static object GetConstExprValue(this Expression exp) + { + if (exp.IsParameter()) return null; + + var expStack = new Stack(); + var exp2 = exp; + while (true) + { + switch (exp2?.NodeType) + { + case ExpressionType.Constant: + expStack.Push(exp2); + break; + case ExpressionType.MemberAccess: + expStack.Push(exp2); + exp2 = (exp2 as MemberExpression).Expression; + if (exp2 == null) break; + continue; + case ExpressionType.Call: + return Expression.Lambda(exp).Compile().DynamicInvoke(); + case ExpressionType.TypeAs: + case ExpressionType.Convert: + var oper2 = (exp2 as UnaryExpression).Operand; + if (oper2.NodeType == ExpressionType.Parameter) + { + var oper2Parm = oper2 as ParameterExpression; + expStack.Push(exp2.Type.IsAbstract || exp2.Type.IsInterface ? oper2Parm : Expression.Parameter(exp2.Type, oper2Parm.Name)); + } + else + expStack.Push(oper2); + break; + } + break; + } + object firstValue = null; + switch (expStack.First().NodeType) + { + case ExpressionType.Constant: + var expStackFirst = expStack.Pop() as ConstantExpression; + firstValue = expStackFirst?.Value; + break; + case ExpressionType.MemberAccess: + var expStackFirstMem = expStack.First() as MemberExpression; + if (expStackFirstMem.Expression?.NodeType == ExpressionType.Constant) + firstValue = (expStackFirstMem.Expression as ConstantExpression)?.Value; + else + return Expression.Lambda(exp).Compile().DynamicInvoke(); + break; + } + while (expStack.Any()) + { + var expStackItem = expStack.Pop(); + switch (expStackItem.NodeType) + { + case ExpressionType.MemberAccess: + var memExp = expStackItem as MemberExpression; + if (memExp.Member.MemberType == MemberTypes.Property) + firstValue = ((PropertyInfo)memExp.Member).GetValue(firstValue, null); + else if (memExp.Member.MemberType == MemberTypes.Field) + firstValue = ((FieldInfo)memExp.Member).GetValue(firstValue); + break; + } + } + return firstValue; + } } internal class NewExpressionVisitor : ExpressionVisitor diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 6408f09d..be8688b0 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -3249,6 +3249,177 @@ + + + 测试数据库是否连接正确,本方法执行如下命令: + MySql/SqlServer/PostgreSQL/达梦/人大金仓/神通: SELECT 1 + Oracle: SELECT 1 FROM dual + + 命令超时设置(秒) + + true: 成功, false: 失败 + + + + 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】 + + + + + + + + + + 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + + 查询 + + + + + + + + + 查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + + 查询 + + + + + + + + + 查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + + 查询 + + + + + + + + + 查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + + 在【主库】执行 + + + + + + + + + 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + + 在【主库】执行 + + + + + + + + + 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + + 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + + + 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 }) + + + + + + + + + + + + 执行SQL返回对象集合,Query<User, Address>("select * from user where age > @age; select * from address", new { age = 25 }) + 提示:parms 参数还可以传 Dictionary<string, object> + + + + + + + + 可自定义解析表达式 @@ -4143,6 +4314,12 @@ 超时 + + + 获取资源 + + + 使用完毕后,归还资源 @@ -4218,6 +4395,12 @@ 资源对象 + + + 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象 + + 资源对象 + 归还对象给对象池的时候触发 diff --git a/FreeSql/Interface/IAop.cs b/FreeSql/Interface/IAop.cs index 9de02937..47f7ed03 100644 --- a/FreeSql/Interface/IAop.cs +++ b/FreeSql/Interface/IAop.cs @@ -92,12 +92,15 @@ namespace FreeSql.Aop #region ParseExpression public class ParseExpressionEventArgs : EventArgs { - public ParseExpressionEventArgs(Expression expression, Func freeParse) + public ParseExpressionEventArgs(Expression expression, Func freeParse, List tables) { this.Expression = expression; this.FreeParse = freeParse; + this.Tables = tables; } + public List Tables { get; } + /// /// 内置解析功能,可辅助您进行解析 /// diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 01278f96..05616d72 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -714,10 +714,15 @@ namespace FreeSql.Internal { if (exp == null) return ""; if (tsc.dbParams != null && tsc.mapColumnTmp != null && tsc.mapColumnTmp.CsType.NullableTypeOrThis() != exp.Type) tsc.SetMapColumnTmp(null); - if (tsc.isDisableDiyParse == false && _common._orm.Aop.ParseExpressionHandler != null) + if (tsc.isDisableDiyParse == false) { - var args = new Aop.ParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(ukexp, tsc.CloneDisableDiyParse())); - _common._orm.Aop.ParseExpressionHandler?.Invoke(this, args); + var args = new Aop.ParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(ukexp, tsc.CloneDisableDiyParse()), tsc._tables); + if (_common._orm.Aop.ParseExpressionHandler != null) + { + _common._orm.Aop.ParseExpressionHandler(this, args); + if (string.IsNullOrEmpty(args.Result) == false) return args.Result; + } + ParseExpressionNoAsSelect(this, args); if (string.IsNullOrEmpty(args.Result) == false) return args.Result; } switch (exp.NodeType) @@ -1240,6 +1245,26 @@ namespace FreeSql.Internal 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(")"); + + switch (exp3.Method.Name) + { + case "Sum": + case "Min": + case "Max": + case "Avg": + var map = new ReadAnonymousTypeInfo(); + var field = new StringBuilder(); + var index = -1; + + for (var a = 0; a < exp3Args0.Parameters.Count; a++) fsqls0p._tables[a].Parameter = exp3Args0.Parameters[a]; + ReadAnonymousField(fsqls0p._tables, field, map, ref index, exp3Args0, null, null, null, null, false); + var fieldSql = field.Length > 0 ? field.Remove(0, 2).ToString() : null; + + var sql4 = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { $"{exp3.Method.Name.ToLower()}({fieldSql})" })?.ToString(); + asSelectBefores.Clear(); + return $"({sql4.Replace(" \r\n", " \r\n ")})"; + } + var sql3 = manySubSelectAggMethod.Invoke(fsql, new object[] { exp3Args0, FieldAliasOptions.AsProperty }) as string; asSelectBefores.Clear(); return $"({sql3.Replace(" \r\n", " \r\n ")})"; @@ -1900,5 +1925,283 @@ namespace FreeSql.Internal return string.Format(CultureInfo.InvariantCulture, "{0}", _ado.AddslashesProcessParam(obj, mapType, mapColumn)); //return string.Concat(_ado.AddslashesProcessParam(obj, mapType, mapColumn)); } + + public static void ParseExpressionNoAsSelect(object sender, Aop.ParseExpressionEventArgs e) + { + if (e.Expression.NodeType != ExpressionType.Call && + (e.Expression as MemberExpression)?.Member.Name != "Count") return; + var exp3Stack = new Stack(); + var exp3tmp = e.Expression; + while (exp3tmp != null) + { + exp3Stack.Push(exp3tmp); + switch (exp3tmp.NodeType) + { + case ExpressionType.Call: + var exp3tmpCall = (exp3tmp as MethodCallExpression); + if (exp3tmpCall.Type.FullName.StartsWith("FreeSql.ISelect`") && exp3tmpCall.Method.Name == "AsSelect" && exp3tmpCall.Object == null) return; + exp3tmp = exp3tmpCall.Object == null ? exp3tmpCall.Arguments.FirstOrDefault() : exp3tmpCall.Object; + continue; + case ExpressionType.MemberAccess: + exp3tmp = (exp3tmp as MemberExpression).Expression; + continue; + case ExpressionType.Parameter: + exp3tmp = null; + continue; + } + return; + } + exp3tmp = exp3Stack.Pop(); + if (exp3tmp.NodeType != ExpressionType.Parameter) return; + if (exp3tmp.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate")) return; + var commonExp = sender as FreeSql.Internal.CommonExpression; + if (commonExp == null) return; + var exp3Tb = commonExp._common.GetTableByEntity(exp3tmp.Type); + if (exp3Tb == null) return; + var paramExp = exp3tmp as ParameterExpression; + Select1Provider select = null; + TableRef memberTbref = null; + MemberExpression memberExp = null; + bool selectSetAliased = false; + + void LocalSetSelectProviderAlias(string alias) + { + if (selectSetAliased) return; + selectSetAliased = true; + select._tables[0].Alias = alias; + select._tables[0].AliasInit = alias; + switch (memberTbref.RefType) + { + case TableRefType.ManyToMany: + var mtmReftbname = e.FreeParse(Expression.MakeMemberAccess(memberExp.Expression, exp3Tb.Properties[exp3Tb.ColumnsByPosition[0].CsName])); + mtmReftbname = mtmReftbname.Substring(0, mtmReftbname.Length - commonExp._common.QuoteSqlName(exp3Tb.ColumnsByPosition[0].Attribute.Name).Length - 1); + var midSelect = commonExp._common._orm.Select().As($"M{select._tables[0].Alias}_M{mtmReftbname}").AsType(memberTbref.RefMiddleEntityType) as Select1Provider; + switch (commonExp._ado.DataType) + { + case DataType.Oracle: + case DataType.OdbcOracle: + case DataType.Dameng: + case DataType.OdbcDameng: + case DataType.GBase: + break; + default: + midSelect.Limit(1); //#462 ORACLE rownum <= 2 会影响索引变慢 + break; + } + for (var tidx = 0; tidx < memberTbref.RefColumns.Count; tidx++) + 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 ")})"); + break; + case TableRefType.OneToMany: + var omtReftbname = e.FreeParse(Expression.MakeMemberAccess(memberExp.Expression, exp3Tb.Properties[exp3Tb.ColumnsByPosition[0].CsName])); + omtReftbname = omtReftbname.Substring(0, omtReftbname.Length - commonExp._common.QuoteSqlName(exp3Tb.ColumnsByPosition[0].Attribute.Name).Length - 1); + 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; + } + + } + void LocalInitSelectProvider() + { + select = commonExp._common._orm.Select().AsType(memberTbref.RefEntityType) as Select1Provider; + select._tables.AddRange(e.Tables.Select(a => new SelectTableInfo + { + Alias = a.Alias, + On = "1=1", + Table = a.Table, + Type = SelectTableInfoType.Parent, + Parameter = a.Parameter + })); + } + while (true) + { + var exp4 = exp3Stack.Pop(); + if (exp4.NodeType == ExpressionType.MemberAccess) + { + var tmpExp = exp4 as MemberExpression; + if (tmpExp.Member.Name == "Count" && select != null) + { + if (exp3Stack.Any()) return; + LocalSetSelectProviderAlias("tbcou"); + e.Result = $"({select.ToSql("count(1)").Replace(" \r\n", " \r\n ")})"; + return; + } + if (select != null) return; + memberExp = tmpExp; + memberTbref = exp3Tb.GetTableRef(memberExp.Member.Name, false); + if (memberTbref == null) return; + switch (memberTbref.RefType) + { + case TableRefType.ManyToOne: + case TableRefType.OneToOne: + exp3Tb = commonExp._common.GetTableByEntity(memberExp.Type); + if (exp3Tb == null) return; + continue; + case TableRefType.ManyToMany: + if (select != null) return; + LocalInitSelectProvider(); + continue; + case TableRefType.OneToMany: + if (select != null) return; + LocalInitSelectProvider(); + continue; + } + } + if (exp4.NodeType == ExpressionType.Call) + { + if (select == null) return; + var callExp = exp4 as MethodCallExpression; + switch (callExp.Method.Name) + { + case "Any": + if (callExp.Arguments.Count == 2) + { + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.InternalWhere(callExp.Arguments[1]); + } + switch (commonExp._ado.DataType) + { + case DataType.Oracle: + case DataType.OdbcOracle: + case DataType.Dameng: + case DataType.OdbcDameng: + case DataType.GBase: + break; + default: + select._limit = 1; //#462 ORACLE rownum <= 2 会影响索引变慢 + break; + } + if (exp3Stack.Any()) return; + LocalSetSelectProviderAlias("tbany"); + e.Result = $"exists({select.ToSql("1").Replace(" \r\n", " \r\n ")})"; + return; + case "Max": + case "Min": + case "Sum": + case "Average": + if (callExp.Arguments.Count == 2) + { + var aggregateMethodName = callExp.Method.Name == "Average" ? "avg" : callExp.Method.Name.ToLower(); + if (exp3Stack.Any()) return; + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + + var map = new ReadAnonymousTypeInfo(); + var field = new StringBuilder(); + var index = -1; + + commonExp.ReadAnonymousField(select._tables, field, map, ref index, callExp.Arguments[1], null, null, null, null, false); + var fieldSql = field.Length > 0 ? field.Remove(0, 2).ToString() : null; + + e.Result = $"({select.ToSql($"{aggregateMethodName}({fieldSql})").Replace(" \r\n", " \r\n ")})"; + return; + } + throw throwCallExp($"不支持 {callExp.Arguments.Count}个参数的方法"); + case "Count": + if (callExp.Arguments.Count == 2) + { + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.InternalWhere(callExp.Arguments[1]); + } + if (exp3Stack.Any()) return; + LocalSetSelectProviderAlias("tbcou"); + e.Result = $"({select.ToSql("count(1)").Replace(" \r\n", " \r\n ")})"; + return; + + case "First": + select.Limit(1); + if (callExp.Arguments.Count == 1) + { + if (exp3Stack.Any()) return; + LocalSetSelectProviderAlias("tbfirst"); + e.Result = $"({select.ToSql().Replace(" \r\n", " \r\n ")})"; + return; + } + throw throwCallExp(" 不支持"); + case "ToList": + if (callExp.Arguments.Count == 1) + { + if (exp3Stack.Any()) return; + LocalSetSelectProviderAlias("tbtolist"); + e.Result = $"({select.ToSql().Replace(" \r\n", " \r\n ")})"; + return; + } + throw throwCallExp(" 不支持"); + case "Contains": + if (callExp.Arguments.Count == 2) + { + if (exp3Stack.Any()) return; + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + e.Result = $"({e.FreeParse(callExp.Arguments[1])}) in {select.ToSql().Replace(" \r\n", " \r\n ")})"; + return; + } + throw throwCallExp($" 不支持 {callExp.Arguments.Count}个参数的方法"); + + case "Distinct": + if (callExp.Arguments.Count == 1) + { + select.Distinct(); + break; + } + throw throwCallExp(" 不支持"); + case "OrderBy": + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.OrderByReflection(callExp.Arguments[1] as LambdaExpression as LambdaExpression, false); + break; + case "OrderByDescending": + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.OrderByReflection(callExp.Arguments[1] as LambdaExpression as LambdaExpression, true); + break; + case "ThenBy": + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.OrderByReflection(callExp.Arguments[1] as LambdaExpression as LambdaExpression, false); + break; + case "ThenByDescending": + select._tables[0].Parameter = (callExp.Arguments[1] as LambdaExpression)?.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.OrderByReflection(callExp.Arguments[1] as LambdaExpression as LambdaExpression, true); + break; + + case "Where": + var whereParam = callExp.Arguments[1] as LambdaExpression; + if (whereParam?.Parameters.Count == 1) + { + select._tables[0].Parameter = whereParam.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select.InternalWhere(whereParam); + break; + } + throw throwCallExp(" 不支持"); + + case "Skip": + select.Offset((int)callExp.Arguments[1].GetConstExprValue()); + break; + case "Take": + select.Limit((int)callExp.Arguments[1].GetConstExprValue()); + break; + + case "Select": + var selectParam = callExp.Arguments[1] as LambdaExpression; + if (selectParam?.Parameters.Count == 1) + { + select._tables[0].Parameter = selectParam.Parameters.FirstOrDefault(); + LocalSetSelectProviderAlias(select._tables[0].Parameter.Name); + select._selectExpression = selectParam; + break; + } + throw throwCallExp(" 不支持"); + } + Exception throwCallExp(string message) => new Exception($"解析失败 {callExp.Method.Name} {message}"); + } + } + } } } diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 08fc5aff..1aa460ea 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -41,6 +41,7 @@ namespace FreeSql.Internal if (common.CodeFirst.GetDbInfo(entity) != null) return null; if (typeof(IEnumerable).IsAssignableFrom(entity) && entity.IsGenericType == true) return null; if (entity.IsArray) return null; + if (entity.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) return null; object entityDefault = null; try diff --git a/README.md b/README.md index 608dbe2c..c337f788 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ fsql.Select().IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name = //ManyToMany fsql.Select() .IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo")) - .Where(s => s.Tags.AsSelect().Any(t => t.Name == "Chinese")) + .Where(s => s.Tags.Any(t => t.Name == "Chinese")) .ToList(); //Other @@ -107,7 +107,7 @@ fsql.Select() .Where(a => a.IsDelete == 0) .WhereIf(keyword != null, a => a.UserName.Contains(keyword)) .WhereIf(role_id > 0, a => a.RoleId == role_id) - .Where(a => a.Nodes.AsSelect().Any(t => t.Parent.Id == t.UserId)) + .Where(a => a.Nodes.Any(t => t.Parent.Id == t.UserId)) .Count(out var total) .Page(page, size) .OrderByDescending(a => a.Id) diff --git a/README.zh-CN.md b/README.zh-CN.md index 3775865d..76b0ec6f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -102,7 +102,7 @@ fsql.Select().IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name = //ManyToMany fsql.Select() .IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo")) - .Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")) + .Where(s => s.Tags.Any(t => t.Name == "国语")) .ToList(); //Other @@ -110,7 +110,7 @@ fsql.Select() .Where(a => a.IsDelete == 0) .WhereIf(keyword != null, a => a.UserName.Contains(keyword)) .WhereIf(role_id > 0, a => a.RoleId == role_id) - .Where(a => a.Nodes.AsSelect().Any(t => t.Parent.Id == t.UserId)) + .Where(a => a.Nodes.Any(t => t.Parent.Id == t.UserId)) .Count(out var total) .Page(page, size) .OrderByDescending(a => a.Id)