Skip to content

Commit f76a46f

Browse files
committed
- 优化 导航集合属性访问,可省略 AsSelect;#15 #300 #362 #509 #698 #644 #903
1 parent dcf7b96 commit f76a46f

File tree

20 files changed

+1949
-348
lines changed

20 files changed

+1949
-348
lines changed

Examples/base_entity/Program.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
namespace base_entity
2525
{
26-
class Program
26+
static class Program
2727
{
2828
class TestConfig
2929
{
@@ -196,6 +196,17 @@ static void Main(string[] args)
196196

197197
fsql.UseJsonMap();
198198

199+
//var txt1 = fsql.Ado.Query<(string, string)>("select '꧁꫞꯭丑小鸭꫞꧂', '123123中国人' from dual");
200+
201+
fsql.Insert(new Order { ShippingAddress = "'꧁꫞꯭丑小鸭꫞꧂'" }).ExecuteAffrows();
202+
fsql.Insert(new Order { ShippingAddress = "'123123中国人'" }).ExecuteAffrows();
203+
var lst1 = fsql.Select<Order>().ToList();
204+
205+
var lst2 = fsql.Select<Order>().ToListIgnore(a => new
206+
{
207+
a.ShippingAddress
208+
});
209+
199210
fsql.Delete<TopicMapTypeToListDto>().Where("1=1").ExecuteAffrows();
200211
fsql.Insert(new[]
201212
{
@@ -794,5 +805,48 @@ int LocalConcurrentDictionaryIsTypeKey(Type dictType, int level = 1)
794805
Console.WriteLine("按任意键结束。。。");
795806
Console.ReadKey();
796807
}
808+
809+
public static List<T1> ToListIgnore<T1>(this ISelect<T1> that, Expression<Func<T1, object>> selector)
810+
{
811+
if (selector == null) return that.ToList();
812+
var s0p = that as Select0Provider;
813+
var tb = s0p._tables[0];
814+
var parmExp = tb.Parameter ?? Expression.Parameter(tb.Table.Type, tb.Alias);
815+
var initExps = tb.Table.Columns.Values
816+
.Where(a => a.Attribute.IsIgnore == false)
817+
.Select(a => new
818+
{
819+
exp = Expression.Bind(tb.Table.Properties[a.CsName], Expression.MakeMemberAccess(parmExp, tb.Table.Properties[a.CsName])),
820+
ignored = TestMemberExpressionVisitor.IsExists(selector, Expression.MakeMemberAccess(parmExp, tb.Table.Properties[a.CsName]))
821+
})
822+
.Where(a => a.ignored == false)
823+
.Select(a => a.exp)
824+
.ToArray();
825+
var lambda = Expression.Lambda<Func<T1, T1>>(
826+
Expression.MemberInit(
827+
Expression.New(tb.Table.Type),
828+
initExps
829+
),
830+
parmExp
831+
);
832+
return that.ToList(lambda);
833+
}
834+
class TestMemberExpressionVisitor : ExpressionVisitor
835+
{
836+
public string MemberExpString;
837+
public bool Result { get; private set; }
838+
839+
public static bool IsExists(Expression selector, Expression memberExp)
840+
{
841+
var visitor = new TestMemberExpressionVisitor { MemberExpString = memberExp.ToString() };
842+
visitor.Visit(selector);
843+
return visitor.Result;
844+
}
845+
protected override Expression VisitMember(MemberExpression node)
846+
{
847+
if (!Result && node.ToString() == MemberExpString) Result = true;
848+
return node;
849+
}
850+
}
797851
}
798852
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"profiles": {
3+
"WSL": {
4+
"commandName": "WSL2",
5+
"distributionName": ""
6+
}
7+
}
8+
}

Extensions/FreeSql.Extensions.Linq/ExprHelper.cs

Lines changed: 0 additions & 95 deletions
This file was deleted.

FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs

Lines changed: 156 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using FreeSql.DataAnnotations;
1+
using FreeSql.DataAnnotations;
22
using Newtonsoft.Json;
33
using System;
44
using System.Collections.Generic;
@@ -91,35 +91,166 @@ public partial class Tag
9191
[Fact]
9292
public void AsSelect()
9393
{
94+
var fsql = g.mysql;
95+
9496
//OneToOne、ManyToOne
95-
var t0 = g.mysql.Select<Tag>().Where(a => a.Parent.Parent.Name == "粤语").ToSql();
96-
//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
97-
//FROM `Tag` a
98-
//LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
99-
//LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id`
100-
//WHERE (a__Parent__Parent.`Name` = '粤语')
97+
var t0 = fsql.Select<Tag>().Where(a => a.Parent.Parent.Name == "粤语").ToSql();
98+
fsql.Select<Tag>().Where(a => a.Parent.Parent.Name == "粤语").First();
99+
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
100+
FROM `Tag` a
101+
LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
102+
LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id`
103+
WHERE (a__Parent__Parent.`Name` = '粤语')", t0);
101104

102105
//OneToMany
103-
var t1 = g.mysql.Select<Tag>().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql();
104-
//SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name`
105-
//FROM `Tag` a
106-
//WHERE (exists(SELECT 1
107-
// FROM `Tag` t
108-
// LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id`
109-
// WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`)
110-
// limit 0,1))
106+
var t1 = fsql.Select<Tag>().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql();
107+
fsql.Select<Tag>().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).First();
108+
Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name`
109+
FROM `Tag` a
110+
WHERE (exists(SELECT 1
111+
FROM `Tag` t
112+
LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id`
113+
WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`)
114+
limit 0,1))", t1);
115+
var t11 = fsql.Select<Tag>().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).ToSql();
116+
fsql.Select<Tag>().Where(a => a.Tags.Any(t => t.Parent.Id == 10)).First();
117+
Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name`
118+
FROM `Tag` a
119+
WHERE (exists(SELECT 1
120+
FROM `Tag` t
121+
LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id`
122+
WHERE (t.`Parent_id` = a.`Id`) AND (t__Parent.`Id` = 10)
123+
limit 0,1))", t11);
124+
var t12 = fsql.Select<Tag>().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).ToSql();
125+
fsql.Select<Tag>().Where(a => a.Parent.Tags.Any(t => t.Parent.Id == 10)).First();
126+
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
127+
FROM `Tag` a
128+
LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
129+
WHERE (exists(SELECT 1
130+
FROM `Tag` t
131+
LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id`
132+
WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10)
133+
limit 0,1))", t12);
134+
var t13 = fsql.Select<Tag>().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql();
135+
fsql.Select<Tag>().Where(a => a.Tags.Where(t => t.Parent.Id == 10).Any()).First();
136+
Assert.Equal(@"SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name`
137+
FROM `Tag` a
138+
WHERE (exists(SELECT 1
139+
FROM `Tag` t
140+
LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id`
141+
WHERE (t.`Parent_id` = a.`Id`) AND (t__Parent.`Id` = 10)
142+
limit 0,1))", t13);
143+
var t14 = fsql.Select<Tag>().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).ToSql();
144+
fsql.Select<Tag>().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Any()).First();
145+
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
146+
FROM `Tag` a
147+
LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
148+
WHERE (exists(SELECT 1
149+
FROM `Tag` t
150+
LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id`
151+
WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10)
152+
limit 0,1))", t14);
153+
var t15 = fsql.Select<Tag>().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).ToSql();
154+
fsql.Select<Tag>().Where(a => a.Parent.Tags.Where(t => t.Parent.Id == 10).Select(t => t.Name).ToList().Contains(a.Name)).First();
155+
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
156+
FROM `Tag` a
157+
LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
158+
WHERE (((a.`Name`) in (SELECT t.`Name` as1
159+
FROM `Tag` t
160+
LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id`
161+
WHERE (t.`Parent_id` = a__Parent.`Id`) AND (t__Parent.`Id` = 10))))", t15);
162+
111163

112164
//ManyToMany
113-
var t2 = g.mysql.Select<Song>().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql();
114-
//SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url`
115-
//FROM `Song` a
116-
//WHERE(exists(SELECT 1
117-
// FROM `Song_tag` Mt_Ms
118-
// WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1
119-
// FROM `Tag` t
120-
// WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`)
121-
// limit 0, 1))
122-
// limit 0, 1))
165+
var t2 = fsql.Select<Song>().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql();
166+
fsql.Select<Song>().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).First();
167+
Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url`
168+
FROM `Song` a
169+
WHERE (exists(SELECT 1
170+
FROM `Song_tag` Mt_Ms
171+
WHERE (Mt_Ms.`Song_id` = a.`Id`) AND (exists(SELECT 1
172+
FROM `Tag` t
173+
WHERE (t.`Name` = '国语') AND (t.`Id` = Mt_Ms.`Tag_id`)
174+
limit 0,1))
175+
limit 0,1))", t2);
176+
var t21 = fsql.Select<Song>().Where(s => s.Tags.Any(t => t.Name == "国语")).ToSql();
177+
fsql.Select<Song>().Where(s => s.Tags.Any(t => t.Name == "国语")).First();
178+
Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url`
179+
FROM `Song` a
180+
WHERE (exists(SELECT 1
181+
FROM `Tag` t
182+
WHERE (exists(SELECT 1
183+
FROM `Song_tag` Mt_Ma
184+
WHERE (Mt_Ma.`Tag_id` = t.`Id`) AND (Mt_Ma.`Song_id` = a.`Id`)
185+
limit 0,1)) AND (t.`Name` = '国语')
186+
limit 0,1))", t21);
187+
var t22 = fsql.Select<Song>().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).ToSql();
188+
fsql.Select<Song>().Where(s => s.Tags.Where(t => t.Name == "国语").Any()).First();
189+
Assert.Equal(@"SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url`
190+
FROM `Song` a
191+
WHERE (exists(SELECT 1
192+
FROM `Tag` t
193+
WHERE (exists(SELECT 1
194+
FROM `Song_tag` Mt_Ma
195+
WHERE (Mt_Ma.`Tag_id` = t.`Id`) AND (Mt_Ma.`Song_id` = a.`Id`)
196+
limit 0,1)) AND (t.`Name` = '国语')
197+
limit 0,1))", t22);
198+
var t23 = fsql.Select<Tag>().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).ToSql();
199+
fsql.Select<Tag>().Where(t => t.Parent.Songs.Any(s => s.Title == "中国人")).First();
200+
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
201+
FROM `Tag` a
202+
LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
203+
WHERE (exists(SELECT 1
204+
FROM `Song` s
205+
WHERE (exists(SELECT 1
206+
FROM `Song_tag` Ms_Ma__Parent
207+
WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`)
208+
limit 0,1)) AND (s.`Title` = '中国人')
209+
limit 0,1))", t23);
210+
var t24 = fsql.Select<Tag>().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).ToSql();
211+
fsql.Select<Tag>().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Any()).First();
212+
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
213+
FROM `Tag` a
214+
LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
215+
WHERE (exists(SELECT 1
216+
FROM `Song` s
217+
WHERE (exists(SELECT 1
218+
FROM `Song_tag` Ms_Ma__Parent
219+
WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`)
220+
limit 0,1)) AND (s.`Title` = '中国人')
221+
limit 0,1))", t24);
222+
var t25 = fsql.Select<Tag>().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).ToSql();
223+
fsql.Select<Tag>().Where(t => t.Parent.Songs.Where(s => s.Title == "中国人").Select(s => s.Title).ToList().Contains(t.Name)).First();
224+
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
225+
FROM `Tag` a
226+
LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id`
227+
WHERE (((a.`Name`) in (SELECT s.`Title` as1
228+
FROM `Song` s
229+
WHERE (exists(SELECT 1
230+
FROM `Song_tag` Ms_Ma__Parent
231+
WHERE (Ms_Ma__Parent.`Song_id` = s.`Id`) AND (Ms_Ma__Parent.`Tag_id` = a__Parent.`Id`)
232+
limit 0,1)) AND (s.`Title` = '中国人'))))", t25);
233+
234+
235+
var t3 = fsql.Select<Song>().ToList(r => new
236+
{
237+
r.Title,
238+
c2 = r.Tags.Count,
239+
c3 = r.Tags.Count(),
240+
c4 = r.Tags.Count(tag => tag.Id > 0),
241+
s1 = r.Tags.Sum(b => b.Id + 0),
242+
a1 = r.Tags.Average(b => b.Id + 1),
243+
m1 = r.Tags.Max(b => b.Id + 2),
244+
m2 = r.Tags.Min(b => b.Id + 3),
245+
f1 = r.Tags.Select(b => b.Name).First(),
246+
247+
count = r.Tags.AsSelect().Count(),
248+
sum = r.Tags.AsSelect().Sum(b => b.Id + 0),
249+
avg = r.Tags.AsSelect().Avg(b => b.Id + 1),
250+
max = r.Tags.AsSelect().Max(b => b.Id + 2),
251+
min = r.Tags.AsSelect().Min(b => b.Id + 3),
252+
first = r.Tags.AsSelect().First(b => b.Name)
253+
});
123254
}
124255

125256
[Fact]

0 commit comments

Comments
 (0)