mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 02:32:50 +08:00
Include 贪婪加载第一版,已通过集合的导航数据加载,包括 OneToMany/ManyToMany
This commit is contained in:
parent
04547c06f8
commit
4481064f4e
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FreeSql.DbContext" Version="0.5.8" />
|
<PackageReference Include="FreeSql.DbContext" Version="0.5.12.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.8" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||||
<PackageReference Include="xunit" Version="2.4.0" />
|
<PackageReference Include="xunit" Version="2.4.0" />
|
||||||
|
@ -756,5 +756,64 @@ namespace FreeSql.Tests.Sqlite {
|
|||||||
sql = query.ToSql().Replace("\r\n", "");
|
sql = query.ToSql().Replace("\r\n", "");
|
||||||
Assert.Equal("SELECT a.\"Id\", a.\"Clicks\", a.\"TypeGuid\", a.\"Title\", a.\"CreateTime\" FROM \"tb_topic22AsTable1\" a LEFT JOIN \"TestTypeInfo\" b on b.\"Guid\" = a.\"TypeGuid\" and b.\"Name\" = @bname", sql);
|
Assert.Equal("SELECT a.\"Id\", a.\"Clicks\", a.\"TypeGuid\", a.\"Title\", a.\"CreateTime\" FROM \"tb_topic22AsTable1\" a LEFT JOIN \"TestTypeInfo\" b on b.\"Guid\" = a.\"TypeGuid\" and b.\"Name\" = @bname", sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Include_OneToMany() {
|
||||||
|
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Include_OneToChilds() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Include_ManyToMany() {
|
||||||
|
|
||||||
|
var tag1 = new Tag {
|
||||||
|
Ddd = DateTime.Now.Second,
|
||||||
|
Name = "test_manytoMany_01_中国"
|
||||||
|
};
|
||||||
|
tag1.Id = (int)g.sqlite.Insert(tag1).ExecuteIdentity();
|
||||||
|
var tag2 = new Tag {
|
||||||
|
Ddd = DateTime.Now.Second,
|
||||||
|
Name = "test_manytoMany_02_美国"
|
||||||
|
};
|
||||||
|
tag2.Id = (int)g.sqlite.Insert(tag2).ExecuteIdentity();
|
||||||
|
var tag3 = new Tag {
|
||||||
|
Ddd = DateTime.Now.Second,
|
||||||
|
Name = "test_manytoMany_03_日本"
|
||||||
|
};
|
||||||
|
tag3.Id = (int)g.sqlite.Insert(tag3).ExecuteIdentity();
|
||||||
|
|
||||||
|
var song1 = new Song {
|
||||||
|
Create_time = DateTime.Now,
|
||||||
|
Title = "test_manytoMany_01_我是中国人.mp3",
|
||||||
|
Url = "http://ww.baidu.com/"
|
||||||
|
};
|
||||||
|
song1.Id = (int)g.sqlite.Insert(song1).ExecuteIdentity();
|
||||||
|
var song2 = new Song {
|
||||||
|
Create_time = DateTime.Now,
|
||||||
|
Title = "test_manytoMany_02_爱你一万年.mp3",
|
||||||
|
Url = "http://ww.163.com/"
|
||||||
|
};
|
||||||
|
song2.Id = (int)g.sqlite.Insert(song2).ExecuteIdentity();
|
||||||
|
var song3 = new Song {
|
||||||
|
Create_time = DateTime.Now,
|
||||||
|
Title = "test_manytoMany_03_千年等一回.mp3",
|
||||||
|
Url = "http://ww.sina.com/"
|
||||||
|
};
|
||||||
|
song3.Id = (int)g.sqlite.Insert(song3).ExecuteIdentity();
|
||||||
|
|
||||||
|
g.sqlite.Insert(new Song_tag { Song_id = song1.Id, Tag_id = tag1.Id }).ExecuteAffrows();
|
||||||
|
g.sqlite.Insert(new Song_tag { Song_id = song2.Id, Tag_id = tag1.Id }).ExecuteAffrows();
|
||||||
|
g.sqlite.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag1.Id }).ExecuteAffrows();
|
||||||
|
g.sqlite.Insert(new Song_tag { Song_id = song1.Id, Tag_id = tag2.Id }).ExecuteAffrows();
|
||||||
|
g.sqlite.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag2.Id }).ExecuteAffrows();
|
||||||
|
g.sqlite.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag3.Id }).ExecuteAffrows();
|
||||||
|
|
||||||
|
var songs = g.sqlite.Select<Song>()
|
||||||
|
.IncludeMany(a => a.Tags)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,8 @@ namespace FreeSql.Tests {
|
|||||||
|
|
||||||
public ICollection<Model2> Childs { get; set; }
|
public ICollection<Model2> Childs { get; set; }
|
||||||
|
|
||||||
|
public int M2Id { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Model2 {
|
public class Model2 {
|
||||||
@ -110,6 +112,32 @@ namespace FreeSql.Tests {
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void Test1() {
|
public void Test1() {
|
||||||
|
|
||||||
|
g.sqlite.GetRepository<Model1, int>().Insert(new Model1 {
|
||||||
|
title = "test_" + DateTime.Now.ToString("yyyyMMddHHmmss"),
|
||||||
|
M2Id = DateTime.Now.Second + DateTime.Now.Minute,
|
||||||
|
Childs = new[] {
|
||||||
|
new Model2 {
|
||||||
|
title = "model2Test_title_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "0001",
|
||||||
|
},
|
||||||
|
new Model2 {
|
||||||
|
title = "model2Test_title_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "0002",
|
||||||
|
},
|
||||||
|
new Model2 {
|
||||||
|
title = "model2Test_title_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "0003",
|
||||||
|
},
|
||||||
|
new Model2 {
|
||||||
|
title = "model2Test_title_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "0004",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var includet1 = g.sqlite.Select<Model1>()
|
||||||
|
.IncludeMany(a => a.Childs, s => s.Where(a => a.id > 0))
|
||||||
|
.Where(a => a.id > 10)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var ttt1 = g.sqlite.Select<Model1>().Where(a => a.Childs.AsSelect().Any(b => b.title == "111")).ToList();
|
var ttt1 = g.sqlite.Select<Model1>().Where(a => a.Childs.AsSelect().Any(b => b.title == "111")).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
@ -602,15 +602,28 @@ namespace FreeSql.Extensions.EntityUtil {
|
|||||||
});
|
});
|
||||||
if (_table.Properties.ContainsKey(pn)) {
|
if (_table.Properties.ContainsKey(pn)) {
|
||||||
var prop = _table.Properties[pn];
|
var prop = _table.Properties[pn];
|
||||||
exps.Add(
|
|
||||||
Expression.Assign(
|
if (_table.ColumnsByCs.ContainsKey(pn)) {
|
||||||
Expression.MakeMemberAccess(var1Parm, prop),
|
exps.Add(
|
||||||
Expression.Convert(
|
Expression.Assign(
|
||||||
FreeSql.Internal.Utils.GetDataReaderValueBlockExpression(prop.PropertyType, parm3),
|
Expression.MakeMemberAccess(var1Parm, prop),
|
||||||
prop.PropertyType
|
Expression.Convert(
|
||||||
|
FreeSql.Internal.Utils.GetDataReaderValueBlockExpression(prop.PropertyType, parm3),
|
||||||
|
prop.PropertyType
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
);
|
} else {
|
||||||
|
exps.Add(
|
||||||
|
Expression.Assign(
|
||||||
|
Expression.MakeMemberAccess(var1Parm, prop),
|
||||||
|
Expression.Convert(
|
||||||
|
parm3,
|
||||||
|
prop.PropertyType
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Expression.Lambda<Action<object, string, object>>(Expression.Block(new[] { var1Parm }, exps), new[] { parm1, parm2, parm3 }).Compile();
|
return Expression.Lambda<Action<object, string, object>>(Expression.Block(new[] { var1Parm }, exps), new[] { parm1, parm2, parm3 }).Compile();
|
||||||
});
|
});
|
||||||
|
@ -1263,6 +1263,23 @@
|
|||||||
<param name="column">列</param>
|
<param name="column">列</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelect`1.Include``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
|
||||||
|
<summary>
|
||||||
|
贪婪加载导航属性,如果查询中已经使用了 a.Parent.Parent 类似表达式,则可以无需此操作
|
||||||
|
</summary>
|
||||||
|
<typeparam name="TNavigate"></typeparam>
|
||||||
|
<param name="navigateSelector">选择一个导航属性</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelect`1.IncludeMany``1(System.Linq.Expressions.Expression{System.Func{`0,System.Collections.Generic.ICollection{``0}}},System.Action{FreeSql.ISelect{``0}})">
|
||||||
|
<summary>
|
||||||
|
贪婪加载集合的导航属性,其实是分两次查询,ToList 后进行了数据重装
|
||||||
|
</summary>
|
||||||
|
<typeparam name="TNavigate"></typeparam>
|
||||||
|
<param name="navigateSelector">选择一个集合的导航属性</param>
|
||||||
|
<param name="then">即能 ThenInclude,还可以二次过滤(这个 EFCore 做不到?)</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:FreeSql.ISelectFromExpression`1.Where(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
<member name="M:FreeSql.ISelectFromExpression`1.Where(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
|
||||||
<summary>
|
<summary>
|
||||||
查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com")
|
查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com")
|
||||||
|
@ -293,5 +293,21 @@ namespace FreeSql {
|
|||||||
/// <param name="column">列</param>
|
/// <param name="column">列</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column);
|
ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 贪婪加载导航属性,如果查询中已经使用了 a.Parent.Parent 类似表达式,则可以无需此操作
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TNavigate"></typeparam>
|
||||||
|
/// <param name="navigateSelector">选择一个导航属性</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
ISelect<T1> Include<TNavigate>(Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class;
|
||||||
|
/// <summary>
|
||||||
|
/// 贪婪加载集合的导航属性,其实是分两次查询,ToList 后进行了数据重装
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TNavigate"></typeparam>
|
||||||
|
/// <param name="navigateSelector">选择一个集合的导航属性</param>
|
||||||
|
/// <param name="then">即能 ThenInclude,还可以二次过滤(这个 EFCore 做不到?)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
ISelect<T1> IncludeMany<TNavigate>(Expression<Func<T1, ICollection<TNavigate>>> navigateSelector, Action<ISelect<TNavigate>> then = null) where TNavigate : class;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -330,7 +330,7 @@ namespace FreeSql.Internal {
|
|||||||
static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
|
static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
|
||||||
static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
|
static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
|
||||||
static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectAnyMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
|
static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectAnyMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
|
||||||
static ConcurrentDictionary<Type, PropertyInfo> _dicNullableValueProperty = new ConcurrentDictionary<Type, PropertyInfo>();
|
internal static ConcurrentDictionary<Type, PropertyInfo> _dicNullableValueProperty = new ConcurrentDictionary<Type, PropertyInfo>();
|
||||||
static ConcurrentDictionary<Type, Expression> _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary<Type, Expression>();
|
static ConcurrentDictionary<Type, Expression> _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary<Type, Expression>();
|
||||||
|
|
||||||
internal string ExpressionBinary(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc) {
|
internal string ExpressionBinary(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc) {
|
||||||
|
@ -30,6 +30,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
protected DbTransaction _transaction;
|
protected DbTransaction _transaction;
|
||||||
protected DbConnection _connection;
|
protected DbConnection _connection;
|
||||||
protected Action<object> _trackToList;
|
protected Action<object> _trackToList;
|
||||||
|
protected Queue<Action<object>> _includeToList = new Queue<Action<object>>();
|
||||||
protected bool _distinct;
|
protected bool _distinct;
|
||||||
protected Expression _selectExpression;
|
protected Expression _selectExpression;
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
toType.GetField("_transaction", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._transaction);
|
toType.GetField("_transaction", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._transaction);
|
||||||
toType.GetField("_connection", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._connection);
|
toType.GetField("_connection", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._connection);
|
||||||
toType.GetField("_trackToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._trackToList);
|
toType.GetField("_trackToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._trackToList);
|
||||||
|
toType.GetField("_includeToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._includeToList);
|
||||||
toType.GetField("_distinct", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._distinct);
|
toType.GetField("_distinct", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._distinct);
|
||||||
toType.GetField("_selectExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._selectExpression);
|
toType.GetField("_selectExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._selectExpression);
|
||||||
}
|
}
|
||||||
@ -318,7 +320,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af) {
|
internal List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af, (ReadAnonymousTypeInfo, List<object>)[] otherData) {
|
||||||
var sql = this.ToSql(af.Field);
|
var sql = this.ToSql(af.Field);
|
||||||
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
|
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
|
||||||
|
|
||||||
@ -331,6 +333,11 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
try {
|
try {
|
||||||
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
|
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
|
||||||
ret.Add(af.Read(_orm, dr));
|
ret.Add(af.Read(_orm, dr));
|
||||||
|
if (otherData != null) {
|
||||||
|
var idx = af.FieldCount - 1;
|
||||||
|
foreach (var other in otherData)
|
||||||
|
other.Item2.Add(_commonExpression.ReadAnonymous(other.Item1, dr, ref idx, false));
|
||||||
|
}
|
||||||
}, CommandType.Text, sql, dbParms);
|
}, CommandType.Text, sql, dbParms);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
exception = ex;
|
exception = ex;
|
||||||
@ -339,12 +346,13 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
|
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
|
||||||
_orm.Aop.CurdAfter?.Invoke(this, after);
|
_orm.Aop.CurdAfter?.Invoke(this, after);
|
||||||
}
|
}
|
||||||
|
while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret);
|
||||||
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
|
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
|
||||||
_trackToList?.Invoke(ret);
|
_trackToList?.Invoke(ret);
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async Task<List<T1>> ToListPrivateAsync(GetAllFieldExpressionTreeInfo af) {
|
async internal Task<List<T1>> ToListPrivateAsync(GetAllFieldExpressionTreeInfo af, (ReadAnonymousTypeInfo, List<object>)[] otherData) {
|
||||||
var sql = this.ToSql(af.Field);
|
var sql = this.ToSql(af.Field);
|
||||||
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
|
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
|
||||||
|
|
||||||
@ -357,6 +365,11 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
try {
|
try {
|
||||||
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
|
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
|
||||||
ret.Add(af.Read(_orm, dr));
|
ret.Add(af.Read(_orm, dr));
|
||||||
|
if (otherData != null) {
|
||||||
|
var idx = af.FieldCount - 1;
|
||||||
|
foreach (var other in otherData)
|
||||||
|
other.Item2.Add(_commonExpression.ReadAnonymous(other.Item1, dr, ref idx, false));
|
||||||
|
}
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}, CommandType.Text, sql, dbParms);
|
}, CommandType.Text, sql, dbParms);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -366,6 +379,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
|
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
|
||||||
_orm.Aop.CurdAfter?.Invoke(this, after);
|
_orm.Aop.CurdAfter?.Invoke(this, after);
|
||||||
}
|
}
|
||||||
|
while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret);
|
||||||
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
|
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
|
||||||
_trackToList?.Invoke(ret);
|
_trackToList?.Invoke(ret);
|
||||||
return ret;
|
return ret;
|
||||||
@ -373,11 +387,11 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
}
|
}
|
||||||
public List<T1> ToList(bool includeNestedMembers = false) {
|
public List<T1> ToList(bool includeNestedMembers = false) {
|
||||||
if (_selectExpression != null) return this.InternalToList<T1>(_selectExpression);
|
if (_selectExpression != null) return this.InternalToList<T1>(_selectExpression);
|
||||||
return this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
|
return this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll(), null);
|
||||||
}
|
}
|
||||||
public Task<List<T1>> ToListAsync(bool includeNestedMembers = false) {
|
public Task<List<T1>> ToListAsync(bool includeNestedMembers = false) {
|
||||||
if (_selectExpression != null) return this.InternalToListAsync<T1>(_selectExpression);
|
if (_selectExpression != null) return this.InternalToListAsync<T1>(_selectExpression);
|
||||||
return this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
|
return this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll(), null);
|
||||||
}
|
}
|
||||||
public T1 ToOne() {
|
public T1 ToOne() {
|
||||||
this.Limit(1);
|
this.Limit(1);
|
||||||
@ -460,6 +474,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
static ConcurrentDictionary<string, GetAllFieldExpressionTreeInfo> _dicGetAllFieldExpressionTree = new ConcurrentDictionary<string, GetAllFieldExpressionTreeInfo>();
|
static ConcurrentDictionary<string, GetAllFieldExpressionTreeInfo> _dicGetAllFieldExpressionTree = new ConcurrentDictionary<string, GetAllFieldExpressionTreeInfo>();
|
||||||
public class GetAllFieldExpressionTreeInfo {
|
public class GetAllFieldExpressionTreeInfo {
|
||||||
public string Field { get; set; }
|
public string Field { get; set; }
|
||||||
|
public int FieldCount { get; set; }
|
||||||
public Func<IFreeSql, DbDataReader, T1> Read { get; set; }
|
public Func<IFreeSql, DbDataReader, T1> Read { get; set; }
|
||||||
}
|
}
|
||||||
protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevelAll() {
|
protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevelAll() {
|
||||||
@ -579,6 +594,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
});
|
});
|
||||||
return new GetAllFieldExpressionTreeInfo {
|
return new GetAllFieldExpressionTreeInfo {
|
||||||
Field = field.ToString(),
|
Field = field.ToString(),
|
||||||
|
FieldCount = index,
|
||||||
Read = Expression.Lambda<Func<IFreeSql, DbDataReader, T1>>(Expression.Block(new[] { retExp, dataIndexExp, readExp }, blockExp), new[] { ormExp, rowExp }).Compile()
|
Read = Expression.Lambda<Func<IFreeSql, DbDataReader, T1>>(Expression.Block(new[] { retExp, dataIndexExp, readExp }, blockExp), new[] { ormExp, rowExp }).Compile()
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
using FreeSql.Internal.Model;
|
using FreeSql.Extensions.EntityUtil;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
using System.Data.Common;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -64,7 +69,6 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalAvg<TMember>(column?.Body);
|
return this.InternalAvg<TMember>(column?.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TMember> AvgAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
public Task<TMember> AvgAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
||||||
if (column == null) return Task.FromResult(default(TMember));
|
if (column == null) return Task.FromResult(default(TMember));
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
@ -73,19 +77,12 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
|
|
||||||
public abstract ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) where T2 : class;// { this.InternalFrom(exp?.Body); var ret = new Select3Provider<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) where T2 : class;// { this.InternalFrom(exp?.Body); var ret = new Select3Provider<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
public abstract ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class;// { this.InternalFrom(exp?.Body); var ret = new Select3Provider<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class;// { this.InternalFrom(exp?.Body); var ret = new Select3Provider<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public abstract ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class;// { this.InternalFrom(exp?.Body); var ret = new Select4Provider<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class;// { this.InternalFrom(exp?.Body); var ret = new Select4Provider<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class;// { this.InternalFrom(exp?.Body); var ret = new Select5Provider<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class;// { this.InternalFrom(exp?.Body); var ret = new Select5Provider<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class;// { this.InternalFrom(exp?.Body); var ret = new Select6Provider<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class;// { this.InternalFrom(exp?.Body); var ret = new Select6Provider<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class;// { this.InternalFrom(exp?.Body); var ret = new Select7Provider<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class;// { this.InternalFrom(exp?.Body); var ret = new Select7Provider<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class;// { this.InternalFrom(exp?.Body); var ret = new Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class;// { this.InternalFrom(exp?.Body); var ret = new Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class;// { this.InternalFrom(exp?.Body); var ret = new Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class;// { this.InternalFrom(exp?.Body); var ret = new Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class;// { this.InternalFrom(exp?.Body); var ret = new Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
public abstract ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class;// { this.InternalFrom(exp?.Body); var ret = new Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, exp?.Parameters); return ret; }
|
||||||
|
|
||||||
public ISelectGrouping<TKey, T1> GroupBy<TKey>(Expression<Func<T1, TKey>> columns) {
|
public ISelectGrouping<TKey, T1> GroupBy<TKey>(Expression<Func<T1, TKey>> columns) {
|
||||||
@ -99,7 +96,6 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalMax<TMember>(column?.Body);
|
return this.InternalMax<TMember>(column?.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TMember> MaxAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
public Task<TMember> MaxAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
||||||
if (column == null) return Task.FromResult(default(TMember));
|
if (column == null) return Task.FromResult(default(TMember));
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
@ -111,7 +107,6 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalMin<TMember>(column?.Body);
|
return this.InternalMin<TMember>(column?.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TMember> MinAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
public Task<TMember> MinAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
||||||
if (column == null) return Task.FromResult(default(TMember));
|
if (column == null) return Task.FromResult(default(TMember));
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
@ -123,7 +118,6 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalOrderBy(column?.Body);
|
return this.InternalOrderBy(column?.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column) {
|
public ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column) {
|
||||||
if (column == null) return this;
|
if (column == null) return this;
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
@ -135,7 +129,6 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
return this.InternalSum<TMember>(column?.Body);
|
return this.InternalSum<TMember>(column?.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TMember> SumAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
public Task<TMember> SumAsync<TMember>(Expression<Func<T1, TMember>> column) {
|
||||||
if (column == null) return Task.FromResult(default(TMember));
|
if (column == null) return Task.FromResult(default(TMember));
|
||||||
_tables[0].Parameter = column.Parameters[0];
|
_tables[0].Parameter = column.Parameters[0];
|
||||||
@ -152,8 +145,8 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
_tables[0].Parameter = select.Parameters[0];
|
_tables[0].Parameter = select.Parameters[0];
|
||||||
return this.InternalToListAsync<TReturn>(select?.Body);
|
return this.InternalToListAsync<TReturn>(select?.Body);
|
||||||
}
|
}
|
||||||
List<TDto> ISelect<T1>.ToList<TDto>() => ToList(GetToListDtoSelector<TDto>());
|
public List<TDto> ToList<TDto>() => ToList(GetToListDtoSelector<TDto>());
|
||||||
Task<List<TDto>> ISelect<T1>.ToListAsync<TDto>() => ToListAsync(GetToListDtoSelector<TDto>());
|
public Task<List<TDto>> ToListAsync<TDto>() => ToListAsync(GetToListDtoSelector<TDto>());
|
||||||
Expression<Func<T1, TDto>> GetToListDtoSelector<TDto>() {
|
Expression<Func<T1, TDto>> GetToListDtoSelector<TDto>() {
|
||||||
var ctor = typeof(TDto).GetConstructor(new Type[0]);
|
var ctor = typeof(TDto).GetConstructor(new Type[0]);
|
||||||
return Expression.Lambda<Func<T1, TDto>>(Expression.New(ctor),
|
return Expression.Lambda<Func<T1, TDto>>(Expression.New(ctor),
|
||||||
@ -310,5 +303,259 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
public TReturn First<TReturn>(Expression<Func<T1, TReturn>> select) => this.ToOne(select);
|
public TReturn First<TReturn>(Expression<Func<T1, TReturn>> select) => this.ToOne(select);
|
||||||
|
|
||||||
public Task<TReturn> FirstAsync<TReturn>(Expression<Func<T1, TReturn>> select) => this.ToOneAsync(select);
|
public Task<TReturn> FirstAsync<TReturn>(Expression<Func<T1, TReturn>> select) => this.ToOneAsync(select);
|
||||||
|
|
||||||
|
public ISelect<T1> Include<TNavigate>(Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class {
|
||||||
|
var expBody = navigateSelector?.Body;
|
||||||
|
if (expBody == null) return this;
|
||||||
|
var tb = _commonUtils.GetTableByEntity(expBody.Type);
|
||||||
|
if (tb == null) throw new Exception("Include 参数类型错误");
|
||||||
|
|
||||||
|
_commonExpression.ExpressionWhereLambda(_tables, Expression.MakeMemberAccess(expBody, tb.Properties[tb.ColumnsByCs.First().Value.CsName]), null);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MethodInfo GetEntityValueWithPropertyNameMethod = typeof(EntityUtilExtensions).GetMethod("GetEntityValueWithPropertyName");
|
||||||
|
static ConcurrentDictionary<Type, ConcurrentDictionary<string, MethodInfo>> _dicTypeMethod = new ConcurrentDictionary<Type, ConcurrentDictionary<string, MethodInfo>>();
|
||||||
|
public ISelect<T1> IncludeMany<TNavigate>(Expression<Func<T1, ICollection<TNavigate>>> navigateSelector, Action<ISelect<TNavigate>> then = null) where TNavigate : class {
|
||||||
|
var expBody = navigateSelector?.Body;
|
||||||
|
if (expBody == null) return this;
|
||||||
|
if (expBody.NodeType != ExpressionType.MemberAccess) throw new Exception("IncludeMany 参数1 类型错误,表达式类型应该为 MemberAccess");
|
||||||
|
var collMem = expBody as MemberExpression;
|
||||||
|
Expression tmpExp = collMem.Expression;
|
||||||
|
var members = new Stack<MemberInfo>();
|
||||||
|
var isbreak = false;
|
||||||
|
while(isbreak == false) {
|
||||||
|
switch (tmpExp.NodeType) {
|
||||||
|
case ExpressionType.MemberAccess:
|
||||||
|
var memExp = tmpExp as MemberExpression;
|
||||||
|
tmpExp = memExp.Expression;
|
||||||
|
members.Push(memExp.Member);
|
||||||
|
continue;
|
||||||
|
case ExpressionType.Parameter:
|
||||||
|
isbreak = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("IncludeMany 参数1 类型错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var tb = _commonUtils.GetTableByEntity(collMem.Expression.Type);
|
||||||
|
if (tb == null) throw new Exception("IncludeMany 参数1 类型错误");
|
||||||
|
|
||||||
|
if (collMem.Expression.NodeType != ExpressionType.Parameter)
|
||||||
|
_commonExpression.ExpressionWhereLambda(_tables, Expression.MakeMemberAccess(collMem.Expression, tb.Properties[tb.ColumnsByCs.First().Value.CsName]), null);
|
||||||
|
var tbref = tb.GetTableRef(collMem.Member.Name, true);
|
||||||
|
|
||||||
|
_includeToList.Enqueue(listObj => {
|
||||||
|
var list = listObj as List<T1>;
|
||||||
|
if (list == null) return;
|
||||||
|
if (list.Any() == false) return;
|
||||||
|
|
||||||
|
var t1parm = Expression.Parameter(typeof(T1));
|
||||||
|
Expression membersExp = t1parm;
|
||||||
|
while (members.Any()) membersExp = Expression.MakeMemberAccess(membersExp, members.Pop());
|
||||||
|
|
||||||
|
var listValueExp = Expression.Parameter(typeof(List<TNavigate>), "listValue");
|
||||||
|
var setListValue = Expression.Lambda<Action<T1, List<TNavigate>>>(
|
||||||
|
Expression.Assign(
|
||||||
|
Expression.MakeMemberAccess(membersExp, collMem.Member),
|
||||||
|
Expression.TypeAs(listValueExp, collMem.Type)
|
||||||
|
), t1parm, listValueExp).Compile();
|
||||||
|
|
||||||
|
var returnTarget = Expression.Label(typeof(object));
|
||||||
|
var propertyNameExp = Expression.Parameter(typeof(string), "propertyName");
|
||||||
|
var getListValue = Expression.Lambda<Func<T1, string, object>>(
|
||||||
|
Expression.Block(
|
||||||
|
Expression.Return(returnTarget, Expression.Call(null, GetEntityValueWithPropertyNameMethod, Expression.Constant(_orm), Expression.Constant(membersExp.Type), membersExp, propertyNameExp)),
|
||||||
|
Expression.Label(returnTarget, Expression.Default(typeof(object)))
|
||||||
|
), t1parm, propertyNameExp).Compile();
|
||||||
|
|
||||||
|
foreach (var item in list) {
|
||||||
|
setListValue(item, null);
|
||||||
|
}
|
||||||
|
var subSelect = _orm.Select<TNavigate>().WithConnection(_connection).WithTransaction(_transaction).TrackToList(_trackToList);
|
||||||
|
if (_tableRules?.Any() == true)
|
||||||
|
foreach (var tr in _tableRules) subSelect.AsTable(tr);
|
||||||
|
|
||||||
|
switch (tbref.RefType) {
|
||||||
|
case TableRefType.OneToMany:
|
||||||
|
if (true) {
|
||||||
|
var tbref2 = _commonUtils.GetTableByEntity(tbref.RefEntityType);
|
||||||
|
if (tbref.Columns.Count == 1) {
|
||||||
|
var arrExp = Expression.NewArrayInit(tbref.Columns[0].CsType, list.Select(a => Expression.Constant(Convert.ChangeType(getListValue(a, tbref.Columns[0].CsName), tbref.Columns[0].CsType))).ToArray());
|
||||||
|
var otmExpParm1 = Expression.Parameter(typeof(TNavigate), "a");
|
||||||
|
var containsMethod = _dicTypeMethod.GetOrAdd(tbref.Columns[0].CsType, et => new ConcurrentDictionary<string, MethodInfo>()).GetOrAdd("Contains", mn =>
|
||||||
|
typeof(Enumerable).GetMethods().Where(a => a.Name == mn).First()).MakeGenericMethod(tbref.Columns[0].CsType);
|
||||||
|
var refCol = Expression.MakeMemberAccess(otmExpParm1, tbref2.Properties[tbref.RefColumns[0].CsName]);
|
||||||
|
if (refCol.Type.IsNullableType()) refCol = Expression.Property(refCol, CommonExpression._dicNullableValueProperty.GetOrAdd(refCol.Type, ct1 => ct1.GetProperty("Value")));
|
||||||
|
subSelect.Where(Expression.Lambda<Func<TNavigate, bool>>(
|
||||||
|
Expression.Call(null, containsMethod, arrExp, refCol), otmExpParm1));
|
||||||
|
} else {
|
||||||
|
var otmExpParm1 = Expression.Parameter(typeof(TNavigate), "a");
|
||||||
|
Expression expOr = null;
|
||||||
|
foreach (var item in list) {
|
||||||
|
Expression expAnd = null;
|
||||||
|
for (var z = 0; z < tbref.Columns.Count; z++) {
|
||||||
|
var colVal = getListValue(item, tbref.Columns[z].CsName);
|
||||||
|
var expTmp = Expression.Equal(Expression.MakeMemberAccess(otmExpParm1, tbref2.Properties[tbref.RefColumns[0].CsName]), Expression.Constant(colVal));
|
||||||
|
if (z == 0) expAnd = expTmp;
|
||||||
|
else expAnd = Expression.AndAlso(expAnd, expTmp);
|
||||||
|
}
|
||||||
|
if (expOr == null) expOr = expAnd;
|
||||||
|
else expOr = Expression.OrElse(expOr, expAnd);
|
||||||
|
}
|
||||||
|
subSelect.Where(Expression.Lambda<Func<TNavigate, bool>>(expOr, otmExpParm1));
|
||||||
|
}
|
||||||
|
then?.Invoke(subSelect);
|
||||||
|
var subList = subSelect.ToList(true);
|
||||||
|
if (subList.Any() == false) {
|
||||||
|
foreach (var item in list)
|
||||||
|
setListValue(item, new List<TNavigate>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, Tuple<T1, List<TNavigate>>> dicList = new Dictionary<string, Tuple<T1, List<TNavigate>>>();
|
||||||
|
foreach (var item in list) {
|
||||||
|
if (tbref.Columns.Count == 1) {
|
||||||
|
dicList.Add(getListValue(item, tbref.Columns[0].CsName).ToString(), Tuple.Create(item, new List<TNavigate>()));
|
||||||
|
} else {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (var z = 0; z < tbref.Columns.Count; z++) {
|
||||||
|
if (z > 0) sb.Append("*$*");
|
||||||
|
sb.Append(getListValue(item, tbref.Columns[z].CsName));
|
||||||
|
}
|
||||||
|
dicList.Add(sb.Remove(0, 3).ToString(), Tuple.Create(item, new List<TNavigate>()));
|
||||||
|
sb.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var parentNavs = new List<string>();
|
||||||
|
foreach (var navProp in tbref2.Properties) {
|
||||||
|
if (tbref2.ColumnsByCs.ContainsKey(navProp.Key)) continue;
|
||||||
|
if (tbref2.ColumnsByCsIgnore.ContainsKey(navProp.Key)) continue;
|
||||||
|
var tr2ref = tbref2.GetTableRef(navProp.Key, false);
|
||||||
|
if (tr2ref == null) continue;
|
||||||
|
if (tr2ref.RefType != TableRefType.ManyToOne) continue;
|
||||||
|
if (tr2ref.RefEntityType != tb.Type) continue;
|
||||||
|
parentNavs.Add(navProp.Key);
|
||||||
|
}
|
||||||
|
foreach (var nav in subList) {
|
||||||
|
string key = null;
|
||||||
|
if (tbref.RefColumns.Count == 1) {
|
||||||
|
key = _orm.GetEntityValueWithPropertyName(tbref.RefEntityType, nav, tbref.RefColumns[0].CsName).ToString();
|
||||||
|
} else {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (var z = 0; z < tbref.RefColumns.Count; z++) {
|
||||||
|
if (z > 0) sb.Append("*$*");
|
||||||
|
sb.Append(_orm.GetEntityValueWithPropertyName(tbref.RefEntityType, nav, tbref.RefColumns[z].CsName));
|
||||||
|
}
|
||||||
|
key = sb.ToString();
|
||||||
|
sb.Clear();
|
||||||
|
}
|
||||||
|
if (dicList.TryGetValue(key, out var t1item) == false) return;
|
||||||
|
t1item.Item2.Add(nav);
|
||||||
|
|
||||||
|
//将子集合的,多对一,对象设置为当前对象
|
||||||
|
foreach (var parentNav in parentNavs)
|
||||||
|
_orm.SetEntityValueWithPropertyName(tbref.RefMiddleEntityType, nav, parentNav, t1item.Item1);
|
||||||
|
}
|
||||||
|
foreach (var t1item in dicList.Values)
|
||||||
|
setListValue(t1item.Item1, t1item.Item2);
|
||||||
|
dicList.Clear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TableRefType.ManyToMany:
|
||||||
|
if (true) {
|
||||||
|
var tbref2 = _commonUtils.GetTableByEntity(tbref.RefEntityType);
|
||||||
|
var tbrefMid = _commonUtils.GetTableByEntity(tbref.RefMiddleEntityType);
|
||||||
|
if (tbref.Columns.Count == 1) {
|
||||||
|
//var midParmExp = Expression.Parameter(tbref.RefMiddleEntityType, "midtb");
|
||||||
|
//(subSelect as Select1Provider<TNavigate>)._tables.Add(new SelectTableInfo {
|
||||||
|
// Alias = "midtb",
|
||||||
|
// AliasInit = "midtb",
|
||||||
|
// On = $"{_commonUtils.QuoteSqlName(tbrefMid.DbName)} midtb ON midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[1].Attribute.Name)} = a.{_commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name)}",
|
||||||
|
// Parameter = midParmExp,
|
||||||
|
// Table = tbrefMid,
|
||||||
|
// Type = SelectTableInfoType.InnerJoin
|
||||||
|
//});
|
||||||
|
subSelect.InnerJoin($"{_commonUtils.QuoteSqlName(tbrefMid.DbName)} midtb ON midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[1].Attribute.Name)} = a.{_commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name)}");
|
||||||
|
subSelect.Where(_commonUtils.FormatSql($"midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[0].Attribute.Name)} in {{0}}", list.Select(a => getListValue(a, tbref.Columns[0].CsName))));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
then?.Invoke(subSelect);
|
||||||
|
|
||||||
|
List<TNavigate> subList = null;
|
||||||
|
List<object> midList = new List<object>();
|
||||||
|
|
||||||
|
var subSelectP1 = (subSelect as Select1Provider<TNavigate>);
|
||||||
|
var af = subSelectP1.GetAllFieldExpressionTreeLevelAll();
|
||||||
|
if (_selectExpression == null) {// return this.InternalToList<T1>(_selectExpression).Select(a => (a, ()).ToList();
|
||||||
|
var sb = new StringBuilder().Append(af.Field);
|
||||||
|
var read = new ReadAnonymousTypeInfo();
|
||||||
|
read.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
|
||||||
|
read.Consturctor = tbrefMid.TypeLazy.GetConstructor(new Type[0]);
|
||||||
|
read.Table = tbrefMid;
|
||||||
|
foreach (var col in tbrefMid.Columns.Values) {
|
||||||
|
if (tbref.MiddleColumns.Where(a => a.CsName == col.CsName).Any() == false) continue;
|
||||||
|
var child = new ReadAnonymousTypeInfo {
|
||||||
|
CsName = col.CsName,
|
||||||
|
CsType = col.CsType,
|
||||||
|
DbField = $"midtb.{_commonUtils.QuoteSqlName(col.Attribute.Name)}",
|
||||||
|
MapType = col.Attribute.MapType,
|
||||||
|
Property = tbrefMid.Properties[col.CsName]
|
||||||
|
};
|
||||||
|
read.Childs.Add(child);
|
||||||
|
sb.Append(", ").Append(_commonUtils.QuoteReadColumn(child.MapType, child.DbField));
|
||||||
|
}
|
||||||
|
af.Field = sb.ToString();
|
||||||
|
subList = subSelectP1.ToListPrivate(af, new[] { (read, midList) });
|
||||||
|
} else
|
||||||
|
subList = subSelectP1.ToListPrivate(af, null);
|
||||||
|
|
||||||
|
if (subList.Any() == false) {
|
||||||
|
foreach (var item in list)
|
||||||
|
setListValue(item, new List<TNavigate>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, Tuple<T1, List<TNavigate>>> dicList = new Dictionary<string, Tuple<T1, List<TNavigate>>>();
|
||||||
|
foreach (var item in list) {
|
||||||
|
if (tbref.Columns.Count == 1) {
|
||||||
|
dicList.Add(getListValue(item, tbref.Columns[0].CsName).ToString(), Tuple.Create(item, new List<TNavigate>()));
|
||||||
|
} else {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (var z = 0; z < tbref.Columns.Count; z++) {
|
||||||
|
if (z > 0) sb.Append("*$*");
|
||||||
|
sb.Append(getListValue(item, tbref.Columns[z].CsName));
|
||||||
|
}
|
||||||
|
dicList.Add(sb.Remove(0, 3).ToString(), Tuple.Create(item, new List<TNavigate>()));
|
||||||
|
sb.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var a = 0; a < subList.Count; a++) {
|
||||||
|
string key = null;
|
||||||
|
if (tbref.Columns.Count == 1) {
|
||||||
|
key = _orm.GetEntityValueWithPropertyName(tbref.RefMiddleEntityType, midList[a], tbref.MiddleColumns[0].CsName).ToString();
|
||||||
|
} else {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (var z = 0; z < tbref.Columns.Count; z++) {
|
||||||
|
if (z > 0) sb.Append("*$*");
|
||||||
|
sb.Append(_orm.GetEntityValueWithPropertyName(tbref.RefMiddleEntityType, midList[a], tbref.MiddleColumns[z].CsName));
|
||||||
|
}
|
||||||
|
key = sb.ToString();
|
||||||
|
sb.Clear();
|
||||||
|
}
|
||||||
|
if (dicList.TryGetValue(key, out var t1item) == false) return;
|
||||||
|
t1item.Item2.Add(subList[a]);
|
||||||
|
}
|
||||||
|
foreach (var t1item in dicList.Values)
|
||||||
|
setListValue(t1item.Item1, t1item.Item2);
|
||||||
|
dicList.Clear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user