mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	补充 ISelect.ToList(a => new XxxDto { XxxId = a.Id, ... }) 支持
This commit is contained in:
		@@ -136,8 +136,20 @@ namespace FreeSql.Tests.MySql {
 | 
				
			|||||||
			var dt2 = select.Limit(10).ToDataTable("id, 111222");
 | 
								var dt2 = select.Limit(10).ToDataTable("id, 111222");
 | 
				
			||||||
			var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
								var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							class TestDto {
 | 
				
			||||||
 | 
								public int id { get; set; }
 | 
				
			||||||
 | 
								public string name { get; set; }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToList() {
 | 
							public void ToList() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var testDto1 = select.Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title });
 | 
				
			||||||
 | 
								var testDto2 = select.Limit(10).ToList(a => new TestDto());
 | 
				
			||||||
 | 
								var testDto3 = select.Limit(10).ToList(a => new TestDto { });
 | 
				
			||||||
 | 
								var testDto4 = select.Limit(10).ToList(a => new TestDto() { });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var t0 = select.Limit(50).ToList();
 | 
								var t0 = select.Limit(50).ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,8 +128,17 @@ namespace FreeSql.Tests.Oracle {
 | 
				
			|||||||
			var dt2 = select.Limit(10).ToDataTable("id, 111222");
 | 
								var dt2 = select.Limit(10).ToDataTable("id, 111222");
 | 
				
			||||||
			var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
								var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							class TestDto {
 | 
				
			||||||
 | 
								public int id { get; set; }
 | 
				
			||||||
 | 
								public string name { get; set; }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToList() {
 | 
							public void ToList() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var testDto1 = select.Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title });
 | 
				
			||||||
 | 
								var testDto2 = select.Limit(10).ToList(a => new TestDto());
 | 
				
			||||||
 | 
								var testDto3 = select.Limit(10).ToList(a => new TestDto { });
 | 
				
			||||||
 | 
								var testDto4 = select.Limit(10).ToList(a => new TestDto() { });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToOne() {
 | 
							public void ToOne() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,8 +119,19 @@ namespace FreeSql.Tests.PostgreSQL {
 | 
				
			|||||||
			var dt2 = select.Limit(10).ToDataTable("id, 222");
 | 
								var dt2 = select.Limit(10).ToDataTable("id, 222");
 | 
				
			||||||
			var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
								var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							class TestDto {
 | 
				
			||||||
 | 
								public int id { get; set; }
 | 
				
			||||||
 | 
								public string name { get; set; }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToList() {
 | 
							public void ToList() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var testDto1 = select.Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title });
 | 
				
			||||||
 | 
								var testDto2 = select.Limit(10).ToList(a => new TestDto());
 | 
				
			||||||
 | 
								var testDto3 = select.Limit(10).ToList(a => new TestDto { });
 | 
				
			||||||
 | 
								var testDto4 = select.Limit(10).ToList(a => new TestDto() { });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var t1 = g.pgsql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToSql();
 | 
								var t1 = g.pgsql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToSql();
 | 
				
			||||||
			var t2 = g.pgsql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToSql();
 | 
								var t2 = g.pgsql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToSql();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -130,8 +130,17 @@ namespace FreeSql.Tests.SqlServer {
 | 
				
			|||||||
			var dt2 = select.Limit(10).ToDataTable("id, getdate()");
 | 
								var dt2 = select.Limit(10).ToDataTable("id, getdate()");
 | 
				
			||||||
			var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
								var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							class TestDto {
 | 
				
			||||||
 | 
								public int id { get; set; }
 | 
				
			||||||
 | 
								public string name { get; set; }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToList() {
 | 
							public void ToList() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var testDto1 = select.Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title });
 | 
				
			||||||
 | 
								var testDto2 = select.Limit(10).ToList(a => new TestDto());
 | 
				
			||||||
 | 
								var testDto3 = select.Limit(10).ToList(a => new TestDto { });
 | 
				
			||||||
 | 
								var testDto4 = select.Limit(10).ToList(a => new TestDto() { });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToOne() {
 | 
							public void ToOne() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,8 +122,17 @@ namespace FreeSql.Tests.Sqlite {
 | 
				
			|||||||
			var dt2 = select.Limit(10).ToDataTable("id, 111222");
 | 
								var dt2 = select.Limit(10).ToDataTable("id, 111222");
 | 
				
			||||||
			var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
								var dt3 = select.Limit(10).ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							class TestDto {
 | 
				
			||||||
 | 
								public int id { get; set; }
 | 
				
			||||||
 | 
								public string name { get; set; }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToList() {
 | 
							public void ToList() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var testDto1 = select.Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title });
 | 
				
			||||||
 | 
								var testDto2 = select.Limit(10).ToList(a => new TestDto());
 | 
				
			||||||
 | 
								var testDto3 = select.Limit(10).ToList(a => new TestDto { });
 | 
				
			||||||
 | 
								var testDto4 = select.Limit(10).ToList(a => new TestDto() { });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void ToOne() {
 | 
							public void ToOne() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			_common = common;
 | 
								_common = common;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static ConcurrentDictionary<Type, PropertyInfo[]> _dicReadAnonymousFieldDtoPropertys = new ConcurrentDictionary<Type, PropertyInfo[]>();
 | 
				
			||||||
		internal bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
							internal bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
				
			||||||
			switch (exp.NodeType) {
 | 
								switch (exp.NodeType) {
 | 
				
			||||||
				case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString);
 | 
									case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString);
 | 
				
			||||||
@@ -78,18 +79,73 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						return false;
 | 
											return false;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return false;
 | 
										return false;
 | 
				
			||||||
 | 
									case ExpressionType.MemberInit:
 | 
				
			||||||
 | 
										var initExp = exp as MemberInitExpression;
 | 
				
			||||||
 | 
										parent.Consturctor = initExp.NewExpression.Type.GetConstructors()[0];
 | 
				
			||||||
 | 
										parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
 | 
				
			||||||
 | 
										if (initExp.Bindings?.Count > 0) {
 | 
				
			||||||
 | 
											//指定 dto映射
 | 
				
			||||||
 | 
											for (var a = 0; a < initExp.Bindings.Count; a++) {
 | 
				
			||||||
 | 
												var initAssignExp = (initExp.Bindings[a] as MemberAssignment);
 | 
				
			||||||
 | 
												if (initAssignExp == null) continue;
 | 
				
			||||||
 | 
												var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
 | 
													Property = initExp.Type.GetProperty(initExp.Bindings[a].Member.Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance),
 | 
				
			||||||
 | 
													CsName = initExp.Bindings[a].Member.Name,
 | 
				
			||||||
 | 
													CsType = initAssignExp.Expression.Type
 | 
				
			||||||
 | 
												};
 | 
				
			||||||
 | 
												parent.Childs.Add(child);
 | 
				
			||||||
 | 
												ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, getSelectGroupingMapString);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											//dto 映射
 | 
				
			||||||
 | 
											var dtoProps = _dicReadAnonymousFieldDtoPropertys.GetOrAdd(initExp.NewExpression.Type, dtoType => dtoType.GetProperties());
 | 
				
			||||||
 | 
											var dtoTb0 = _tables.First();
 | 
				
			||||||
 | 
											foreach (var dtoProp in dtoProps) {
 | 
				
			||||||
 | 
												if (dtoTb0.Table.Columns.TryGetValue(dtoProp.Name, out var trydtocol)) {
 | 
				
			||||||
 | 
													var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
 | 
														Property = dtoProp,
 | 
				
			||||||
 | 
														CsName = dtoProp.Name,
 | 
				
			||||||
 | 
														CsType = dtoProp.PropertyType
 | 
				
			||||||
 | 
													};
 | 
				
			||||||
 | 
													parent.Childs.Add(child);
 | 
				
			||||||
 | 
													ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtoTb0.Parameter, dtoTb0.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString);
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if (parent.Childs.Any() == false) throw new Exception($"映射异常:{initExp.NewExpression.Type.Name} 没有一个属性名和 {dtoTb0.Table.Type.Name} 相同");
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										return true;
 | 
				
			||||||
				case ExpressionType.New:
 | 
									case ExpressionType.New:
 | 
				
			||||||
					var newExp = exp as NewExpression;
 | 
										var newExp = exp as NewExpression;
 | 
				
			||||||
					parent.Consturctor = newExp.Type.GetConstructors()[0];
 | 
										parent.Consturctor = newExp.Type.GetConstructors()[0];
 | 
				
			||||||
					parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Arguments;
 | 
										parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Arguments;
 | 
				
			||||||
 | 
										if (newExp.Members?.Count > 0) {
 | 
				
			||||||
						for (var a = 0; a < newExp.Members.Count; a++) {
 | 
											for (var a = 0; a < newExp.Members.Count; a++) {
 | 
				
			||||||
							var child = new ReadAnonymousTypeInfo {
 | 
												var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
								Property = newExp.Type.GetProperty(newExp.Members[a].Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance),
 | 
													Property = newExp.Type.GetProperty(newExp.Members[a].Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance),
 | 
				
			||||||
							CsName = newExp.Members[a].Name, CsType = newExp.Arguments[a].Type
 | 
													CsName = newExp.Members[a].Name,
 | 
				
			||||||
 | 
													CsType = newExp.Arguments[a].Type
 | 
				
			||||||
							};
 | 
												};
 | 
				
			||||||
							parent.Childs.Add(child);
 | 
												parent.Childs.Add(child);
 | 
				
			||||||
							ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], getSelectGroupingMapString);
 | 
												ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], getSelectGroupingMapString);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											//dto 映射
 | 
				
			||||||
 | 
											parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
 | 
				
			||||||
 | 
											var dtoProps = _dicReadAnonymousFieldDtoPropertys.GetOrAdd(newExp.Type, dtoType => dtoType.GetProperties());
 | 
				
			||||||
 | 
											var dtoTb0 = _tables.First();
 | 
				
			||||||
 | 
											foreach (var dtoProp in dtoProps) {
 | 
				
			||||||
 | 
												if (dtoTb0.Table.Columns.TryGetValue(dtoProp.Name, out var trydtocol)) {
 | 
				
			||||||
 | 
													var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
 | 
														Property = dtoProp,
 | 
				
			||||||
 | 
														CsName = dtoProp.Name,
 | 
				
			||||||
 | 
														CsType = dtoProp.PropertyType
 | 
				
			||||||
 | 
													};
 | 
				
			||||||
 | 
													parent.Childs.Add(child);
 | 
				
			||||||
 | 
													ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtoTb0.Parameter, dtoTb0.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString);
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if (parent.Childs.Any() == false) throw new Exception($"映射异常:{newExp.Type.Name} 没有一个属性名和 {dtoTb0.Table.Type.Name} 相同");
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					return true;
 | 
										return true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			parent.DbField = $"({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where)})";
 | 
								parent.DbField = $"({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where)})";
 | 
				
			||||||
@@ -121,7 +177,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						var prop = parent.Childs[b].Property;
 | 
											var prop = parent.Childs[b].Property;
 | 
				
			||||||
						var objval = ReadAnonymous(parent.Childs[b], dr, ref index, notRead);
 | 
											var objval = ReadAnonymous(parent.Childs[b], dr, ref index, notRead);
 | 
				
			||||||
						var safeval = Utils.GetDataReaderValue(prop.PropertyType, objval);
 | 
											var safeval = Utils.GetDataReaderValue(prop.PropertyType, objval);
 | 
				
			||||||
						if (isnull == false && safeval == null && parent.Table.ColumnsByCs.TryGetValue(parent.Childs[b].CsName, out var trycol) && trycol.Attribute.IsPrimary)
 | 
											if (isnull == false && safeval == null && parent.Table != null && parent.Table.ColumnsByCs.TryGetValue(parent.Childs[b].CsName, out var trycol) && trycol.Attribute.IsPrimary)
 | 
				
			||||||
							isnull = true;
 | 
												isnull = true;
 | 
				
			||||||
						if (isnull == false)
 | 
											if (isnull == false)
 | 
				
			||||||
							prop.SetValue(ret, safeval, null);
 | 
												prop.SetValue(ret, safeval, null);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user