mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	- 修改 IncludeMany ManyToMany ET 缓存的 bug;
- 完善 IncludeMany 联合键处理; - 完善 Include/IncludeMany 单元测试; - 修复 Include 延时加载 ManyToOne/OneToOne,当值为 null 时,仍然会查询一次数据;
This commit is contained in:
		@@ -763,7 +763,69 @@ namespace FreeSql.Tests.Sqlite {
 | 
			
		||||
		}
 | 
			
		||||
		[Fact]
 | 
			
		||||
		public void Include_OneToChilds() {
 | 
			
		||||
			var tag1 = new Tag {
 | 
			
		||||
				Ddd = DateTime.Now.Second,
 | 
			
		||||
				Name = "test_oneToChilds_01_中国"
 | 
			
		||||
			};
 | 
			
		||||
			tag1.Id = (int)g.sqlite.Insert(tag1).ExecuteIdentity();
 | 
			
		||||
			var tag1_1 = new Tag {
 | 
			
		||||
				Parent_id = tag1.Id,
 | 
			
		||||
				Ddd = DateTime.Now.Second,
 | 
			
		||||
				Name = "test_oneToChilds_01_北京"
 | 
			
		||||
			};
 | 
			
		||||
			tag1_1.Id = (int)g.sqlite.Insert(tag1_1).ExecuteIdentity();
 | 
			
		||||
			var tag1_2 = new Tag {
 | 
			
		||||
				Parent_id = tag1.Id,
 | 
			
		||||
				Ddd = DateTime.Now.Second,
 | 
			
		||||
				Name = "test_oneToChilds_01_上海"
 | 
			
		||||
			};
 | 
			
		||||
			tag1_2.Id = (int)g.sqlite.Insert(tag1_2).ExecuteIdentity();
 | 
			
		||||
 | 
			
		||||
			var tag2 = new Tag {
 | 
			
		||||
				Ddd = DateTime.Now.Second,
 | 
			
		||||
				Name = "test_oneToChilds_02_美国"
 | 
			
		||||
			};
 | 
			
		||||
			tag2.Id = (int)g.sqlite.Insert(tag2).ExecuteIdentity();
 | 
			
		||||
			var tag2_1 = new Tag {
 | 
			
		||||
				Parent_id = tag2.Id,
 | 
			
		||||
				Ddd = DateTime.Now.Second,
 | 
			
		||||
				Name = "test_oneToChilds_02_纽约"
 | 
			
		||||
			};
 | 
			
		||||
			tag2_1.Id = (int)g.sqlite.Insert(tag2_1).ExecuteIdentity();
 | 
			
		||||
			var tag2_2 = new Tag {
 | 
			
		||||
				Parent_id = tag2.Id,
 | 
			
		||||
				Ddd = DateTime.Now.Second,
 | 
			
		||||
				Name = "test_oneToChilds_02_华盛顿"
 | 
			
		||||
			};
 | 
			
		||||
			tag2_2.Id = (int)g.sqlite.Insert(tag2_2).ExecuteIdentity();
 | 
			
		||||
 | 
			
		||||
			var tags0 = g.sqlite.Select<Tag>()
 | 
			
		||||
				.Include(a => a.Parent)
 | 
			
		||||
				.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
 | 
			
		||||
				.ToList();
 | 
			
		||||
 | 
			
		||||
			var tags = g.sqlite.Select<Tag>()
 | 
			
		||||
				.IncludeMany(a => a.Tags)
 | 
			
		||||
				.Include(a => a.Parent)
 | 
			
		||||
				.IncludeMany(a => a.Songs)
 | 
			
		||||
				.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
 | 
			
		||||
				.ToList();
 | 
			
		||||
 | 
			
		||||
			var tags2 = g.sqlite.Select<Tag>()
 | 
			
		||||
				.IncludeMany(a => a.Tags,
 | 
			
		||||
					then => then.Include(a => a.Parent).IncludeMany(a => a.Songs))
 | 
			
		||||
				.Include(a => a.Parent)
 | 
			
		||||
				.IncludeMany(a => a.Songs)
 | 
			
		||||
				.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
 | 
			
		||||
				.ToList();
 | 
			
		||||
 | 
			
		||||
			var tags3 = g.sqlite.Select<Tag>()
 | 
			
		||||
				.IncludeMany(a => a.Tags,
 | 
			
		||||
					then => then.Include(a => a.Parent).IncludeMany(a => a.Songs).IncludeMany(a => a.Tags))
 | 
			
		||||
				.Include(a => a.Parent)
 | 
			
		||||
				.IncludeMany(a => a.Songs)
 | 
			
		||||
				.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
 | 
			
		||||
				.ToList();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Fact]
 | 
			
		||||
@@ -813,7 +875,22 @@ namespace FreeSql.Tests.Sqlite {
 | 
			
		||||
 | 
			
		||||
			var songs = g.sqlite.Select<Song>()
 | 
			
		||||
				.IncludeMany(a => a.Tags)
 | 
			
		||||
				.Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id)
 | 
			
		||||
				.ToList();
 | 
			
		||||
			Assert.Equal(3, songs.Count);
 | 
			
		||||
			Assert.Equal(2, songs[0].Tags.Count);
 | 
			
		||||
			Assert.Equal(1, songs[1].Tags.Count);
 | 
			
		||||
			Assert.Equal(3, songs[2].Tags.Count);
 | 
			
		||||
 | 
			
		||||
			var songs2 = g.sqlite.Select<Song>()
 | 
			
		||||
				.IncludeMany(a => a.Tags, 
 | 
			
		||||
					then => then.IncludeMany(t => t.Songs))
 | 
			
		||||
				.Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id)
 | 
			
		||||
				.ToList();
 | 
			
		||||
			Assert.Equal(3, songs2.Count);
 | 
			
		||||
			Assert.Equal(2, songs2[0].Tags.Count);
 | 
			
		||||
			Assert.Equal(1, songs2[1].Tags.Count);
 | 
			
		||||
			Assert.Equal(3, songs2[2].Tags.Count);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<TargetFramework>netstandard2.0</TargetFramework>
 | 
			
		||||
		<Version>0.5.13</Version>
 | 
			
		||||
		<Version>0.5.14</Version>
 | 
			
		||||
		<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
 | 
			
		||||
		<Authors>YeXiangQin</Authors>
 | 
			
		||||
		<Description>FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite.</Description>
 | 
			
		||||
 
 | 
			
		||||
@@ -286,8 +286,6 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
					var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
					_orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
				}
 | 
			
		||||
				_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
 | 
			
		||||
				_trackToList?.Invoke(ret);
 | 
			
		||||
				return ret;
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
@@ -315,13 +313,18 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
					var after = new Aop.CurdAfterEventArgs(before, exception, ret);
 | 
			
		||||
					_orm.Aop.CurdAfter?.Invoke(this, after);
 | 
			
		||||
				}
 | 
			
		||||
				_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
 | 
			
		||||
				_trackToList?.Invoke(ret);
 | 
			
		||||
				return ret;
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
		internal List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af, (ReadAnonymousTypeInfo, List<object>)[] otherData) {
 | 
			
		||||
			var sql = this.ToSql(af.Field);
 | 
			
		||||
		internal List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) {
 | 
			
		||||
			string sql = null;
 | 
			
		||||
			if (otherData?.Length > 0) {
 | 
			
		||||
				var sbField = new StringBuilder().Append(af.Field);
 | 
			
		||||
				foreach (var other in otherData)
 | 
			
		||||
					sbField.Append(other.field);
 | 
			
		||||
				sql = this.ToSql(sbField.ToString());
 | 
			
		||||
			} else
 | 
			
		||||
				sql = this.ToSql(af.Field);
 | 
			
		||||
			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
 | 
			
		||||
 | 
			
		||||
			return _orm.Cache.Shell(_cache.key, _cache.seconds, () => {
 | 
			
		||||
@@ -336,7 +339,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
						if (otherData != null) {
 | 
			
		||||
							var idx = af.FieldCount - 1;
 | 
			
		||||
							foreach (var other in otherData)
 | 
			
		||||
								other.Item2.Add(_commonExpression.ReadAnonymous(other.Item1, dr, ref idx, false));
 | 
			
		||||
								other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false));
 | 
			
		||||
						}
 | 
			
		||||
					}, CommandType.Text, sql, dbParms);
 | 
			
		||||
				} catch (Exception ex) {
 | 
			
		||||
@@ -352,8 +355,15 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
				return ret;
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
		async internal Task<List<T1>> ToListPrivateAsync(GetAllFieldExpressionTreeInfo af, (ReadAnonymousTypeInfo, List<object>)[] otherData) {
 | 
			
		||||
			var sql = this.ToSql(af.Field);
 | 
			
		||||
		async internal Task<List<T1>> ToListPrivateAsync(GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) {
 | 
			
		||||
			string sql = null;
 | 
			
		||||
			if (otherData?.Length > 0) {
 | 
			
		||||
				var sbField = new StringBuilder().Append(af.Field);
 | 
			
		||||
				foreach (var other in otherData)
 | 
			
		||||
					sbField.Append(other.field);
 | 
			
		||||
				sql = this.ToSql(sbField.ToString());
 | 
			
		||||
			} else
 | 
			
		||||
				sql = this.ToSql(af.Field);
 | 
			
		||||
			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
 | 
			
		||||
 | 
			
		||||
			return await _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => {
 | 
			
		||||
@@ -368,7 +378,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
						if (otherData != null) {
 | 
			
		||||
							var idx = af.FieldCount - 1;
 | 
			
		||||
							foreach (var other in otherData)
 | 
			
		||||
								other.Item2.Add(_commonExpression.ReadAnonymous(other.Item1, dr, ref idx, false));
 | 
			
		||||
								other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false));
 | 
			
		||||
						}
 | 
			
		||||
						return Task.CompletedTask;
 | 
			
		||||
					}, CommandType.Text, sql, dbParms);
 | 
			
		||||
@@ -501,13 +511,30 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
				var tb = _tables.First();
 | 
			
		||||
				var index = 0;
 | 
			
		||||
 | 
			
		||||
				var tborder = new[] { tb }.Concat(_tables.ToArray().Where((a, b) => b > 0).OrderBy(a => a.Alias));
 | 
			
		||||
				var tbiindex = 0;
 | 
			
		||||
				foreach (var tbi in _tables.ToArray().OrderBy(a => a.Alias)) {
 | 
			
		||||
				foreach (var tbi in tborder) {
 | 
			
		||||
					if (tbiindex > 0 && tbi.Type == SelectTableInfoType.From) continue;
 | 
			
		||||
					if (tbiindex > 0 && tbi.Alias.StartsWith($"{tb.Alias}__") == false) continue;
 | 
			
		||||
 | 
			
		||||
					var typei = tbi.Table.TypeLazy ?? tbi.Table.Type;
 | 
			
		||||
					Expression curExp = retExp;
 | 
			
		||||
 | 
			
		||||
					var colidx = 0;
 | 
			
		||||
					foreach (var col in tbi.Table.Columns.Values) {
 | 
			
		||||
						if (index > 0) {
 | 
			
		||||
							field.Append(", ");
 | 
			
		||||
							if (tbiindex > 0 && colidx == 0) field.Append("\r\n");
 | 
			
		||||
						}
 | 
			
		||||
						var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
			
		||||
						field.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"{tbi.Alias}.{quoteName}"));
 | 
			
		||||
						++index;
 | 
			
		||||
						if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
			
		||||
						else dicfield.Add(quoteName, true);
 | 
			
		||||
						++colidx;
 | 
			
		||||
					}
 | 
			
		||||
					tbiindex++;
 | 
			
		||||
 | 
			
		||||
					if (tbiindex == 0)
 | 
			
		||||
						blockExp.AddRange(new Expression[] {
 | 
			
		||||
							Expression.Assign(readExp, Expression.Call(Utils.MethodExecuteArrayRowReadClassOrTuple, new Expression[] { Expression.Constant(typei), Expression.Constant(null, typeof(int[])), rowExp, dataIndexExp, Expression.Constant(_commonUtils) })),
 | 
			
		||||
@@ -547,7 +574,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
						if (iscontinue) continue;
 | 
			
		||||
 | 
			
		||||
						blockExp.Add(
 | 
			
		||||
							Expression.IfThen(
 | 
			
		||||
							Expression.IfThenElse(
 | 
			
		||||
								curExpIfNotNull,
 | 
			
		||||
								Expression.Block(new Expression[] {
 | 
			
		||||
									Expression.Assign(readExp, Expression.Call(Utils.MethodExecuteArrayRowReadClassOrTuple, new Expression[] { Expression.Constant(typei), Expression.Constant(null, typeof(int[])), rowExp, dataIndexExp, Expression.Constant(_commonUtils) })),
 | 
			
		||||
@@ -555,11 +582,16 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
										Expression.GreaterThan(readExpDataIndex, dataIndexExp),
 | 
			
		||||
										Expression.Assign(dataIndexExp, readExpDataIndex)
 | 
			
		||||
									),
 | 
			
		||||
									Expression.IfThen(
 | 
			
		||||
									Expression.IfThenElse(
 | 
			
		||||
										Expression.NotEqual(readExpValue, Expression.Constant(null)),
 | 
			
		||||
										Expression.Assign(curExp, Expression.Convert(readExpValue, typei))
 | 
			
		||||
										Expression.Assign(curExp, Expression.Convert(readExpValue, typei)),
 | 
			
		||||
										Expression.Assign(curExp, Expression.Constant(null, typei))
 | 
			
		||||
									)
 | 
			
		||||
								})
 | 
			
		||||
								}),
 | 
			
		||||
								Expression.Block(
 | 
			
		||||
									Expression.Assign(readExpValue, Expression.Constant(null, typeof(object))),
 | 
			
		||||
									Expression.Assign(dataIndexExp, Expression.Constant(index))
 | 
			
		||||
								)
 | 
			
		||||
							)
 | 
			
		||||
						);
 | 
			
		||||
					}
 | 
			
		||||
@@ -571,21 +603,6 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
								Expression.Call(Expression.TypeAs(readExpValue, typei), tbi.Table.TypeLazySetOrm, ormExp)
 | 
			
		||||
							)
 | 
			
		||||
						); //将 orm 传递给 lazy
 | 
			
		||||
 | 
			
		||||
					var colidx = 0;
 | 
			
		||||
					foreach (var col in tbi.Table.Columns.Values) {
 | 
			
		||||
						if (index > 0) {
 | 
			
		||||
							field.Append(", ");
 | 
			
		||||
							if (tbiindex > 0 && colidx == 0) field.Append("\r\n");
 | 
			
		||||
						}
 | 
			
		||||
						var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
			
		||||
						field.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"{tbi.Alias}.{quoteName}"));
 | 
			
		||||
						++index;
 | 
			
		||||
						if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
			
		||||
						else dicfield.Add(quoteName, true);
 | 
			
		||||
						++colidx;
 | 
			
		||||
					}
 | 
			
		||||
					tbiindex++;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				blockExp.AddRange(new Expression[] {
 | 
			
		||||
@@ -685,9 +702,17 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
						Expression.IfThen(Expression.GreaterThan(readExpDataIndex, dataIndexExp),
 | 
			
		||||
							Expression.Assign(dataIndexExp, readExpDataIndex)),
 | 
			
		||||
						//Expression.Call(typeof(Trace).GetMethod("WriteLine", new Type[]{typeof(string)}), Expression.Call(typeof(string).GetMethod("Concat", new Type[]{typeof(object) }), readExpValue)),
 | 
			
		||||
						Expression.IfThen(Expression.NotEqual(readExpValue, Expression.Constant(null)),
 | 
			
		||||
							//Expression.Call(retExp, propGetSetMethod, Expression.Default(prop.PropertyType)),
 | 
			
		||||
							Expression.Call(retExp, propGetSetMethod, Expression.Convert(readExpValue, prop.PropertyType)))
 | 
			
		||||
 | 
			
		||||
						tb1.TypeLazy != null ?
 | 
			
		||||
							Expression.IfThenElse(
 | 
			
		||||
								Expression.NotEqual(readExpValue, Expression.Constant(null)),
 | 
			
		||||
								Expression.Call(retExp, propGetSetMethod, Expression.Convert(readExpValue, prop.PropertyType)),
 | 
			
		||||
								Expression.Call(retExp, propGetSetMethod, Expression.Convert(Utils.GetDataReaderValueBlockExpression(prop.PropertyType, Expression.Constant(null)), prop.PropertyType))
 | 
			
		||||
							) :
 | 
			
		||||
							Expression.IfThen(
 | 
			
		||||
								Expression.NotEqual(readExpValue, Expression.Constant(null)),
 | 
			
		||||
								Expression.Call(retExp, propGetSetMethod, Expression.Convert(readExpValue, prop.PropertyType))
 | 
			
		||||
							)
 | 
			
		||||
					});
 | 
			
		||||
				}
 | 
			
		||||
				if (otherindex == 0) { //不读导航属性,优化单表读取性能
 | 
			
		||||
 
 | 
			
		||||
@@ -343,13 +343,15 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
 | 
			
		||||
			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 tbref = tb.GetTableRef(collMem.Member.Name, true);
 | 
			
		||||
				if (tbref.Columns.Any() == false) return;
 | 
			
		||||
 | 
			
		||||
				var t1parm = Expression.Parameter(typeof(T1));
 | 
			
		||||
				Expression membersExp = t1parm;
 | 
			
		||||
				while (members.Any()) membersExp = Expression.MakeMemberAccess(membersExp, members.Pop());
 | 
			
		||||
@@ -381,7 +383,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
						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 arrExp = Expression.NewArrayInit(tbref.Columns[0].CsType, list.Select(a => Expression.Constant(Convert.ChangeType(getListValue(a, tbref.Columns[0].CsName), tbref.Columns[0].CsType))).Distinct().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);
 | 
			
		||||
@@ -466,21 +468,34 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
						if (true) {
 | 
			
		||||
							var tbref2 = _commonUtils.GetTableByEntity(tbref.RefEntityType);
 | 
			
		||||
							var tbrefMid = _commonUtils.GetTableByEntity(tbref.RefMiddleEntityType);
 | 
			
		||||
							var sbJoin = new StringBuilder().Append($"{_commonUtils.QuoteSqlName(tbrefMid.DbName)} midtb ON");
 | 
			
		||||
							for (var z = 0; z < tbref.RefColumns.Count; z++) {
 | 
			
		||||
								if (z > 0) sbJoin.Append(" AND");
 | 
			
		||||
								sbJoin.Append($" midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[tbref.Columns.Count + z].Attribute.Name)} = a.{_commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)}");
 | 
			
		||||
							}
 | 
			
		||||
							subSelect.InnerJoin(sbJoin.ToString());
 | 
			
		||||
							sbJoin.Clear();
 | 
			
		||||
							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))));
 | 
			
		||||
								
 | 
			
		||||
								subSelect.Where(_commonUtils.FormatSql($"midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[0].Attribute.Name)} in {{0}}", list.Select(a => getListValue(a, tbref.Columns[0].CsName)).Distinct()));
 | 
			
		||||
							} else {
 | 
			
		||||
								
 | 
			
		||||
								Dictionary<string, bool> sbDic = new Dictionary<string, bool>();
 | 
			
		||||
								for (var y = 0; y < list.Count; y++) {
 | 
			
		||||
									var sbWhereOne = new StringBuilder();
 | 
			
		||||
									sbWhereOne.Append(" (");
 | 
			
		||||
									for (var z = 0; z < tbref.Columns.Count; z++) {
 | 
			
		||||
										if (z > 0) sbWhereOne.Append(" AND");
 | 
			
		||||
										sbWhereOne.Append(_commonUtils.FormatSql($" midtb.{_commonUtils.QuoteSqlName(tbref.MiddleColumns[z].Attribute.Name)}={{0}}", getListValue(list[y], tbref.Columns[z].CsName)));
 | 
			
		||||
									}
 | 
			
		||||
									sbWhereOne.Append(")");
 | 
			
		||||
									var whereOne = sbWhereOne.ToString();
 | 
			
		||||
									sbWhereOne.Clear();
 | 
			
		||||
									if (sbDic.ContainsKey(whereOne) == false) sbDic.Add(whereOne, true);
 | 
			
		||||
								}
 | 
			
		||||
								var sbWhere = new StringBuilder();
 | 
			
		||||
								foreach (var sbd in sbDic)
 | 
			
		||||
									sbWhere.Append(" OR").Append(sbd.Key);
 | 
			
		||||
								subSelect.Where(sbWhere.Remove(0, 3).ToString());
 | 
			
		||||
								sbWhere.Clear();
 | 
			
		||||
							}
 | 
			
		||||
							then?.Invoke(subSelect);
 | 
			
		||||
 | 
			
		||||
@@ -490,7 +505,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
							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 field = new StringBuilder();
 | 
			
		||||
								var read = new ReadAnonymousTypeInfo();
 | 
			
		||||
								read.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
 | 
			
		||||
								read.Consturctor = tbrefMid.TypeLazy.GetConstructor(new Type[0]);
 | 
			
		||||
@@ -505,10 +520,9 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
										Property = tbrefMid.Properties[col.CsName]
 | 
			
		||||
									};
 | 
			
		||||
									read.Childs.Add(child);
 | 
			
		||||
									sb.Append(", ").Append(_commonUtils.QuoteReadColumn(child.MapType, child.DbField));
 | 
			
		||||
									field.Append(", ").Append(_commonUtils.QuoteReadColumn(child.MapType, child.DbField));
 | 
			
		||||
								}
 | 
			
		||||
								af.Field = sb.ToString();
 | 
			
		||||
								subList = subSelectP1.ToListPrivate(af, new[] { (read, midList) });
 | 
			
		||||
								subList = subSelectP1.ToListPrivate(af, new[] { (field.ToString(), read, midList) });
 | 
			
		||||
							} else
 | 
			
		||||
								subList = subSelectP1.ToListPrivate(af, null);
 | 
			
		||||
 | 
			
		||||
@@ -518,17 +532,25 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
								return;
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							Dictionary<string, Tuple<T1, List<TNavigate>>> dicList = new Dictionary<string, Tuple<T1, List<TNavigate>>>();
 | 
			
		||||
							Dictionary<string, List<Tuple<T1, List<TNavigate>>>> dicList = new Dictionary<string, List<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>()));
 | 
			
		||||
									var dicListKey = getListValue(item, tbref.Columns[0].CsName).ToString();
 | 
			
		||||
									var dicListVal = Tuple.Create(item, new List<TNavigate>());
 | 
			
		||||
									if (dicList.TryGetValue(dicListKey, out var items) == false)
 | 
			
		||||
										dicList.Add(dicListKey, items = new List<Tuple<T1, List<TNavigate>>>());
 | 
			
		||||
									items.Add(dicListVal);
 | 
			
		||||
								} 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>()));
 | 
			
		||||
									var dicListKey = sb.Remove(0, 3).ToString();
 | 
			
		||||
									var dicListVal = Tuple.Create(item, new List<TNavigate>());
 | 
			
		||||
									if (dicList.TryGetValue(dicListKey, out var items) == false)
 | 
			
		||||
										dicList.Add(dicListKey, items = new List<Tuple<T1, List<TNavigate>>>());
 | 
			
		||||
									items.Add(dicListVal);
 | 
			
		||||
									sb.Clear();
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
@@ -545,11 +567,13 @@ namespace FreeSql.Internal.CommonProvider {
 | 
			
		||||
									key = sb.ToString();
 | 
			
		||||
									sb.Clear();
 | 
			
		||||
								}
 | 
			
		||||
								if (dicList.TryGetValue(key, out var t1item) == false) return;
 | 
			
		||||
								t1item.Item2.Add(subList[a]);
 | 
			
		||||
								if (dicList.TryGetValue(key, out var t1items) == false) return;
 | 
			
		||||
								foreach (var t1item in t1items)
 | 
			
		||||
									t1item.Item2.Add(subList[a]);
 | 
			
		||||
							}
 | 
			
		||||
							foreach (var t1item in dicList.Values)
 | 
			
		||||
								setListValue(t1item.Item1, t1item.Item2);
 | 
			
		||||
							foreach (var t1items in dicList.Values)
 | 
			
		||||
								foreach (var t1item in t1items)
 | 
			
		||||
									setListValue(t1item.Item1, t1item.Item2);
 | 
			
		||||
							dicList.Clear();
 | 
			
		||||
						}
 | 
			
		||||
						break;
 | 
			
		||||
 
 | 
			
		||||
@@ -605,7 +605,10 @@ namespace FreeSql.Internal {
 | 
			
		||||
								.Append("		}\r\n");
 | 
			
		||||
						}
 | 
			
		||||
						if (vp.Item3) { //set 重写
 | 
			
		||||
							cscode.Append("		set => base.").Append(pnv.Name).AppendLine(" = value;");
 | 
			
		||||
							cscode.Append("		set {\r\n")
 | 
			
		||||
								.Append("			base.").Append(pnv.Name).AppendLine(" = value;")
 | 
			
		||||
								.Append("			__lazy__").Append(pnv.Name).AppendLine(" = true;")
 | 
			
		||||
								.Append("		}\r\n");
 | 
			
		||||
						}
 | 
			
		||||
						cscode.AppendLine("	}");
 | 
			
		||||
					}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user