mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	- 增加 Column.MapType 类型映射,可将 enum 映射为 int/string 等;
This commit is contained in:
		
							
								
								
									
										1562
									
								
								FreeSql.Tests/MySql/MapType/BoolNullableTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1562
									
								
								FreeSql.Tests/MySql/MapType/BoolNullableTest.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1096
									
								
								FreeSql.Tests/MySql/MapType/BoolTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1096
									
								
								FreeSql.Tests/MySql/MapType/BoolTest.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										254
									
								
								FreeSql.Tests/MySql/MapType/EnumTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								FreeSql.Tests/MySql/MapType/EnumTest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
				
			|||||||
 | 
					using FreeSql.DataAnnotations;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Numerics;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace FreeSql.Tests.MySql.MapType {
 | 
				
			||||||
 | 
						public class EnumTest {
 | 
				
			||||||
 | 
							class EnumTestMap {
 | 
				
			||||||
 | 
								public Guid id { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public ToStringMapEnum enum_to_string { get; set; }
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public ToStringMapEnum? enumnullable_to_string { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[Column(MapType = typeof(int))]
 | 
				
			||||||
 | 
								public ToStringMapEnum enum_to_int { get; set; }
 | 
				
			||||||
 | 
								[Column(MapType = typeof(int?))]
 | 
				
			||||||
 | 
								public ToStringMapEnum? enumnullable_to_int { get; set; }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							public enum ToStringMapEnum { <EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, abc, <EFBFBD><EFBFBD><EFBFBD><EFBFBD> }
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void EnumToString() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new EnumTestMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new EnumTestMap { enum_to_string = ToStringMapEnum.abc };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.enum_to_string = ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.enum_to_string = ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void EnumNullableToString() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new EnumTestMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new EnumTestMap { enumnullable_to_string = ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD> };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.enumnullable_to_string = ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.enumnullable_to_string = null;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void EnumToInt() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new EnumTestMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_int, find.enum_to_int);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enum_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new EnumTestMap { enum_to_int = ToStringMapEnum.abc };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_int, find.enum_to_int);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enum_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.enum_to_int = ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_int, find.enum_to_int);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enum_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.enum_to_int = ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_int, find.enum_to_int);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enum_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enum_to_int, ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enum_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enum_to_int, ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enum_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void EnumNullableToInt() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new EnumTestMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new EnumTestMap { enumnullable_to_int = ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD> };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<EnumTestMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enumnullable_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.enumnullable_to_int = ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enumnullable_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.enumnullable_to_int = null;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enumnullable_to_int, ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enumnullable_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<EnumTestMap>().Where(a => a.id == item.id).Set(a => a.enumnullable_to_int, null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.abc).First());
 | 
				
			||||||
 | 
								find = orm.Select<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<EnumTestMap>().Where(a => a.id == item.id && a.enumnullable_to_int == null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<EnumTestMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										557
									
								
								FreeSql.Tests/MySql/MapType/ToStringTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										557
									
								
								FreeSql.Tests/MySql/MapType/ToStringTest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,557 @@
 | 
				
			|||||||
 | 
					using FreeSql.DataAnnotations;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Numerics;
 | 
				
			||||||
 | 
					using Xunit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace FreeSql.Tests.MySql.MapType {
 | 
				
			||||||
 | 
						public class ToStringTest {
 | 
				
			||||||
 | 
							class ToStringMap {
 | 
				
			||||||
 | 
								public Guid id { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public TimeSpan timespan_to_string { get; set; }
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public TimeSpan? timespannullable_to_string { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public DateTime datetime_to_string { get; set; }
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public DateTime? datetimenullable_to_string { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public Guid guid_to_string { get; set; }
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public Guid? guidnullable_to_string { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public ToStringMapEnum enum_to_string { get; set; }
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public ToStringMapEnum? enumnullable_to_string { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public BigInteger biginteger_to_string { get; set; }
 | 
				
			||||||
 | 
								[Column(MapType = typeof(string))]
 | 
				
			||||||
 | 
								public BigInteger? bigintegernullable_to_string { get; set; }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							public enum ToStringMapEnum { <EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, abc, <EFBFBD><EFBFBD><EFBFBD><EFBFBD> }
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void Enum1() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { enum_to_string = ToStringMapEnum.abc };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.enum_to_string = ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.enum_to_string = ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enum_to_string, find.enum_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enum_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void EnumNullable() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { enumnullable_to_string = ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD> };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>, find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.enumnullable_to_string = ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.enumnullable_to_string = null;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).First());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, ToStringMapEnum.abc).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(ToStringMapEnum.abc, find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Null(find.enumnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.enumnullable_to_string == null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void BigInteger1() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 0).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.biginteger_to_string, find.biginteger_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(0, find.biginteger_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { biginteger_to_string = 100 };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 100).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.biginteger_to_string, find.biginteger_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(100, find.biginteger_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.biginteger_to_string = 200;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 200).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.biginteger_to_string, find.biginteger_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(200, find.biginteger_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.biginteger_to_string = 205;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 205).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.biginteger_to_string, find.biginteger_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(205, find.biginteger_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.biginteger_to_string, 522).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 522).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(522, find.biginteger_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.biginteger_to_string, 10005).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 10005).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(10005, find.biginteger_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 522).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 205).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.biginteger_to_string == 10005).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void BigIntegerNullable() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { bigintegernullable_to_string = 101 };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == 101).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(101, find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.bigintegernullable_to_string = 2004;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == 2004).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(2004, find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.bigintegernullable_to_string = null;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == 2004).First());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.bigintegernullable_to_string, 998).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == 998).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(998, find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.bigintegernullable_to_string, null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == 998).First());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Null(find.bigintegernullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == 998).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(0, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == 2004).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void TimeSpan1() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.timespan_to_string, find.timespan_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(TimeSpan.Zero, find.timespan_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { timespan_to_string = TimeSpan.FromDays(1) };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.timespan_to_string, find.timespan_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(TimeSpan.FromDays(1), find.timespan_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.timespan_to_string = TimeSpan.FromHours(10);
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.timespan_to_string, find.timespan_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(TimeSpan.FromHours(10), find.timespan_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.timespan_to_string, TimeSpan.FromHours(11)).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(TimeSpan.FromHours(11), find.timespan_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void TimeSpanNullable() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.timespannullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { timespannullable_to_string = TimeSpan.FromDays(1) };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(TimeSpan.FromDays(1), find.timespannullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.timespannullable_to_string = TimeSpan.FromHours(10);
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(TimeSpan.FromHours(10), find.timespannullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.timespannullable_to_string = null;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.timespannullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.timespannullable_to_string, TimeSpan.FromHours(11)).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(TimeSpan.FromHours(11), find.timespannullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.timespannullable_to_string, null).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Null(find.timespannullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void DateTime1() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.datetime_to_string, find.datetime_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(DateTime.MinValue, find.datetime_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { datetime_to_string = DateTime.Parse("2000-1-1") };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.datetime_to_string, find.datetime_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(DateTime.Parse("2000-1-1"), find.datetime_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.datetime_to_string = DateTime.Parse("2000-1-11");
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.datetime_to_string, find.datetime_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(DateTime.Parse("2000-1-11"), find.datetime_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.datetime_to_string, DateTime.Parse("2000-1-12")).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(DateTime.Parse("2000-1-12"), find.datetime_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void DateTimeNullable() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.datetimenullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item = new ToStringMap { datetimenullable_to_string = DateTime.Parse("2000-1-1") };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(DateTime.Parse("2000-1-1"), find.datetimenullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								item.datetimenullable_to_string = DateTime.Parse("2000-1-11");
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(DateTime.Parse("2000-1-11"), find.datetimenullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.datetimenullable_to_string = null;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.datetimenullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.datetimenullable_to_string, DateTime.Parse("2000-1-12")).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(DateTime.Parse("2000-1-12"), find.datetimenullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.datetimenullable_to_string, null).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Null(find.datetimenullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void Guid1() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guid_to_string == Guid.Empty).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.guid_to_string, find.guid_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(Guid.Empty, find.guid_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var newid = Guid.NewGuid();
 | 
				
			||||||
 | 
								item = new ToStringMap { guid_to_string = newid };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guid_to_string == newid).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.guid_to_string, find.guid_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(newid, find.guid_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								newid = Guid.NewGuid();
 | 
				
			||||||
 | 
								item.guid_to_string = newid;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guid_to_string == newid).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.guid_to_string, find.guid_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(newid, find.guid_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								newid = Guid.NewGuid();
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.guid_to_string, newid).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guid_to_string == newid).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(newid, find.guid_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.guid_to_string == newid).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[Fact]
 | 
				
			||||||
 | 
							public void GuidNullable() {
 | 
				
			||||||
 | 
								//insert
 | 
				
			||||||
 | 
								var orm = g.mysql;
 | 
				
			||||||
 | 
								var item = new ToStringMap { };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								var find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guidnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.guidnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var newid = Guid.NewGuid();
 | 
				
			||||||
 | 
								item = new ToStringMap { guidnullable_to_string = newid };
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Insert<ToStringMap>().AppendData(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guidnullable_to_string == newid).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(newid, find.guidnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update all
 | 
				
			||||||
 | 
								newid = Guid.NewGuid();
 | 
				
			||||||
 | 
								item.guidnullable_to_string = newid;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guidnullable_to_string == newid).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Equal(newid, find.guidnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item.guidnullable_to_string = null;
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().SetSource(item).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guidnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string);
 | 
				
			||||||
 | 
								Assert.Null(find.guidnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//update set
 | 
				
			||||||
 | 
								newid = Guid.NewGuid();
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.guidnullable_to_string, newid).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guidnullable_to_string == newid).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Equal(newid, find.guidnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Update<ToStringMap>().Where(a => a.id == item.id).Set(a => a.guidnullable_to_string, null).ExecuteAffrows());
 | 
				
			||||||
 | 
								find = orm.Select<ToStringMap>().Where(a => a.id == item.id && a.guidnullable_to_string == null).First();
 | 
				
			||||||
 | 
								Assert.NotNull(find);
 | 
				
			||||||
 | 
								Assert.Equal(item.id, find.id);
 | 
				
			||||||
 | 
								Assert.Null(find.guidnullable_to_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//delete
 | 
				
			||||||
 | 
								Assert.Equal(1, orm.Delete<ToStringMap>().Where(a => a.id == item.id && a.guidnullable_to_string == null).ExecuteAffrows());
 | 
				
			||||||
 | 
								Assert.Null(orm.Select<ToStringMap>().Where(a => a.id == item.id).First());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -71,7 +71,7 @@ namespace FreeSql.Tests.PostgreSQLExpression {
 | 
				
			|||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void Log() {
 | 
							public void Log() {
 | 
				
			||||||
			var data = new List<object>();
 | 
								var data = new List<object>();
 | 
				
			||||||
			data.Add(select.Where(a => Math.Log(a.Clicks + 0.5) == a.Clicks + 1).ToList());
 | 
								//data.Add(select.Where(a => Math.Log(a.Clicks + 0.5) == a.Clicks + 1).ToList());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		[Fact]
 | 
							[Fact]
 | 
				
			||||||
		public void Log10() {
 | 
							public void Log10() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,6 @@ namespace FreeSql.DataAnnotations {
 | 
				
			|||||||
		/// <summary>
 | 
							/// <summary>
 | 
				
			||||||
		/// 类型映射,比如:可将 enum 属性映射成 typeof(string)
 | 
							/// 类型映射,比如:可将 enum 属性映射成 typeof(string)
 | 
				
			||||||
		/// </summary>
 | 
							/// </summary>
 | 
				
			||||||
		public Type Mapping { get; set; }
 | 
							public Type MapType { get; set; }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,6 @@
 | 
				
			|||||||
namespace FreeSql.DataAnnotations {
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace FreeSql.DataAnnotations {
 | 
				
			||||||
	public class ColumnFluent {
 | 
						public class ColumnFluent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public ColumnFluent(ColumnAttribute column) {
 | 
							public ColumnFluent(ColumnAttribute column) {
 | 
				
			||||||
@@ -62,5 +64,14 @@
 | 
				
			|||||||
			_column.IsVersion = value;
 | 
								_column.IsVersion = value;
 | 
				
			||||||
			return this;
 | 
								return this;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// 类型映射,比如:可将 enum 属性映射成 typeof(string)
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							/// <param name="type"></param>
 | 
				
			||||||
 | 
							/// <returns></returns>
 | 
				
			||||||
 | 
							public ColumnFluent MapType(Type type) {
 | 
				
			||||||
 | 
								_column.MapType = type;
 | 
				
			||||||
 | 
								return this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,9 +41,10 @@ namespace FreeSql.Extensions.EntityUtil {
 | 
				
			|||||||
					Expression.Assign(var3IsNull, Expression.Constant(false))
 | 
										Expression.Assign(var3IsNull, Expression.Constant(false))
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
				for (var a = 0; a < pks.Length; a++) {
 | 
									for (var a = 0; a < pks.Length; a++) {
 | 
				
			||||||
					var isguid = pks[a].CsType.NullableTypeOrThis() == typeof(Guid);
 | 
										var isguid = pks[a].Attribute.MapType.NullableTypeOrThis() == typeof(Guid) || pks[a].CsType.NullableTypeOrThis() == typeof(Guid);
 | 
				
			||||||
					Expression expthen = null;
 | 
										Expression expthen = null;
 | 
				
			||||||
					if (isguid) {
 | 
										if (isguid) {
 | 
				
			||||||
 | 
											if (pks[a].Attribute.MapType == pks[a].CsType) {
 | 
				
			||||||
							expthen = Expression.Block(
 | 
												expthen = Expression.Block(
 | 
				
			||||||
								new Expression[]{
 | 
													new Expression[]{
 | 
				
			||||||
									Expression.Assign(Expression.MakeMemberAccess(var1Parm, _table.Properties[pks[a].CsName]), Expression.Call(MethodFreeUtilNewMongodbId)),
 | 
														Expression.Assign(Expression.MakeMemberAccess(var1Parm, _table.Properties[pks[a].CsName]), Expression.Call(MethodFreeUtilNewMongodbId)),
 | 
				
			||||||
@@ -53,6 +54,17 @@ namespace FreeSql.Extensions.EntityUtil {
 | 
				
			|||||||
									)
 | 
														)
 | 
				
			||||||
								}.Where(c => c != null).ToArray()
 | 
													}.Where(c => c != null).ToArray()
 | 
				
			||||||
							);
 | 
												);
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												expthen = Expression.Block(
 | 
				
			||||||
 | 
													new Expression[]{
 | 
				
			||||||
 | 
														Expression.Assign(Expression.MakeMemberAccess(var1Parm, _table.Properties[pks[a].CsName]), FreeSql.Internal.Utils.GetDataReaderValueBlockExpression(pks[a].CsType, Expression.Call(MethodFreeUtilNewMongodbId))),
 | 
				
			||||||
 | 
														a > 0 ? Expression.Call(var2Sb, MethodStringBuilderAppend, Expression.Constant(splitString)) : null,
 | 
				
			||||||
 | 
														Expression.Call(var2Sb, MethodStringBuilderAppend,
 | 
				
			||||||
 | 
															Expression.Convert(Expression.MakeMemberAccess(var1Parm, _table.Properties[pks[a].CsName]), typeof(object))
 | 
				
			||||||
 | 
														)
 | 
				
			||||||
 | 
													}.Where(c => c != null).ToArray()
 | 
				
			||||||
 | 
												);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
					} else if (pks.Length > 1 && pks[a].Attribute.IsIdentity) {
 | 
										} else if (pks.Length > 1 && pks[a].Attribute.IsIdentity) {
 | 
				
			||||||
						expthen = Expression.Block(
 | 
											expthen = Expression.Block(
 | 
				
			||||||
								new Expression[]{
 | 
													new Expression[]{
 | 
				
			||||||
@@ -405,14 +417,23 @@ namespace FreeSql.Extensions.EntityUtil {
 | 
				
			|||||||
					Expression.Assign(var1Parm, Expression.TypeAs(parm1, t))
 | 
										Expression.Assign(var1Parm, Expression.TypeAs(parm1, t))
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
				foreach (var pk in _table.Primarys) {
 | 
									foreach (var pk in _table.Primarys) {
 | 
				
			||||||
					if (pk.CsType == typeof(Guid) || pk.CsType == typeof(Guid?) ||
 | 
										if (pk.Attribute.IsIdentity || pk.Attribute.MapType == pk.CsType && pk.Attribute.MapType.NullableTypeOrThis() == typeof(Guid)) {
 | 
				
			||||||
						pk.Attribute.IsIdentity) {
 | 
					 | 
				
			||||||
						exps.Add(
 | 
											exps.Add(
 | 
				
			||||||
							Expression.Assign(
 | 
												Expression.Assign(
 | 
				
			||||||
								Expression.MakeMemberAccess(var1Parm, _table.Properties[pk.CsName]),
 | 
													Expression.MakeMemberAccess(var1Parm, _table.Properties[pk.CsName]),
 | 
				
			||||||
								Expression.Default(pk.CsType)
 | 
													Expression.Default(pk.CsType)
 | 
				
			||||||
							)
 | 
												)
 | 
				
			||||||
						);
 | 
											);
 | 
				
			||||||
 | 
											continue;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if (pk.Attribute.MapType != pk.CsType && (pk.Attribute.MapType.NullableTypeOrThis() == typeof(Guid) || pk.CsType.NullableTypeOrThis() == typeof(Guid))) {
 | 
				
			||||||
 | 
											exps.Add(
 | 
				
			||||||
 | 
												Expression.Assign(
 | 
				
			||||||
 | 
													Expression.MakeMemberAccess(var1Parm, _table.Properties[pk.CsName]),
 | 
				
			||||||
 | 
													FreeSql.Internal.Utils.GetDataReaderValueBlockExpression(pk.CsType, Expression.Default(pk.Attribute.MapType))
 | 
				
			||||||
 | 
												)
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
											continue;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return Expression.Lambda<Action<object>>(Expression.Block(new[] { var1Parm }, exps), new[] { parm1 }).Compile();
 | 
									return Expression.Lambda<Action<object>>(Expression.Block(new[] { var1Parm }, exps), new[] { parm1 }).Compile();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,18 +13,21 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
	internal abstract class CommonExpression {
 | 
						internal abstract class CommonExpression {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal CommonUtils _common;
 | 
							internal CommonUtils _common;
 | 
				
			||||||
 | 
							internal CommonProvider.AdoProvider _ado => _adoPriv ?? (_adoPriv = _common._orm.Ado as CommonProvider.AdoProvider);
 | 
				
			||||||
 | 
							CommonProvider.AdoProvider _adoPriv;
 | 
				
			||||||
		internal CommonExpression(CommonUtils common) {
 | 
							internal CommonExpression(CommonUtils common) {
 | 
				
			||||||
			_common = common;
 | 
								_common = common;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static ConcurrentDictionary<Type, PropertyInfo[]> _dicReadAnonymousFieldDtoPropertys = new ConcurrentDictionary<Type, PropertyInfo[]>();
 | 
							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) {
 | 
				
			||||||
 | 
								Func<ExpTSC> getTSC = () => new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where };
 | 
				
			||||||
			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);
 | 
				
			||||||
				case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, getSelectGroupingMapString);
 | 
									case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, getSelectGroupingMapString);
 | 
				
			||||||
				case ExpressionType.Negate:
 | 
									case ExpressionType.Negate:
 | 
				
			||||||
				case ExpressionType.NegateChecked:
 | 
									case ExpressionType.NegateChecked:
 | 
				
			||||||
					parent.DbField = $"-({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where)})";
 | 
										parent.DbField = $"-({ExpressionLambdaToSql(exp, getTSC())})";
 | 
				
			||||||
					field.Append(", ").Append(parent.DbField);
 | 
										field.Append(", ").Append(parent.DbField);
 | 
				
			||||||
					if (index >= 0) field.Append(" as").Append(++index);
 | 
										if (index >= 0) field.Append(" as").Append(++index);
 | 
				
			||||||
					return false;
 | 
										return false;
 | 
				
			||||||
@@ -51,7 +54,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						callExp.Arguments[0].Type.FullName == "System.String")
 | 
											callExp.Arguments[0].Type.FullName == "System.String")
 | 
				
			||||||
						parent.DbField = (callExp.Arguments[0] as ConstantExpression).Value?.ToString() ?? "NULL";
 | 
											parent.DbField = (callExp.Arguments[0] as ConstantExpression).Value?.ToString() ?? "NULL";
 | 
				
			||||||
					else
 | 
										else
 | 
				
			||||||
						parent.DbField = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where);
 | 
											parent.DbField = ExpressionLambdaToSql(exp, getTSC());
 | 
				
			||||||
					field.Append(", ").Append(parent.DbField);
 | 
										field.Append(", ").Append(parent.DbField);
 | 
				
			||||||
					if (index >= 0) field.Append(" as").Append(++index);
 | 
										if (index >= 0) field.Append(" as").Append(++index);
 | 
				
			||||||
					return false;
 | 
										return false;
 | 
				
			||||||
@@ -67,17 +70,19 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
							var child = new ReadAnonymousTypeInfo {
 | 
												var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
								Property = tb.Properties.TryGetValue(map[idx].Column.CsName, out var tryprop) ? tryprop : tb.Type.GetProperty(map[idx].Column.CsName, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance),
 | 
													Property = tb.Properties.TryGetValue(map[idx].Column.CsName, out var tryprop) ? tryprop : tb.Type.GetProperty(map[idx].Column.CsName, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance),
 | 
				
			||||||
								CsName = map[idx].Column.CsName, DbField = $"{map[idx].Table.Alias}.{_common.QuoteSqlName(map[idx].Column.Attribute.Name)}",
 | 
													CsName = map[idx].Column.CsName, DbField = $"{map[idx].Table.Alias}.{_common.QuoteSqlName(map[idx].Column.Attribute.Name)}",
 | 
				
			||||||
								CsType = map[idx].Column.CsType
 | 
													CsType = map[idx].Column.CsType,
 | 
				
			||||||
 | 
													MapType = map[idx].Column.Attribute.MapType
 | 
				
			||||||
							};
 | 
												};
 | 
				
			||||||
							field.Append(", ").Append(_common.QuoteReadColumn(map[idx].Column.CsType, child.DbField));
 | 
												field.Append(", ").Append(_common.QuoteReadColumn(child.MapType, child.DbField));
 | 
				
			||||||
							if (index >= 0) field.Append(" as").Append(++index);
 | 
												if (index >= 0) field.Append(" as").Append(++index);
 | 
				
			||||||
							parent.Childs.Add(child);
 | 
												parent.Childs.Add(child);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						parent.CsType = exp.Type;
 | 
											parent.CsType = exp.Type;
 | 
				
			||||||
						parent.DbField = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where);
 | 
											parent.DbField = ExpressionLambdaToSql(exp, getTSC());
 | 
				
			||||||
						field.Append(", ").Append(parent.DbField);
 | 
											field.Append(", ").Append(parent.DbField);
 | 
				
			||||||
						if (index >= 0) field.Append(" as").Append(++index);
 | 
											if (index >= 0) field.Append(" as").Append(++index);
 | 
				
			||||||
 | 
											parent.MapType = SearchColumnByField(_tables, null, parent.DbField)?.Attribute.MapType ?? exp.Type;
 | 
				
			||||||
						return false;
 | 
											return false;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return false;
 | 
										return false;
 | 
				
			||||||
@@ -93,7 +98,8 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
							var child = new ReadAnonymousTypeInfo {
 | 
												var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
								Property = initExp.Type.GetProperty(initExp.Bindings[a].Member.Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance),
 | 
													Property = initExp.Type.GetProperty(initExp.Bindings[a].Member.Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance),
 | 
				
			||||||
								CsName = initExp.Bindings[a].Member.Name,
 | 
													CsName = initExp.Bindings[a].Member.Name,
 | 
				
			||||||
								CsType = initAssignExp.Expression.Type
 | 
													CsType = initAssignExp.Expression.Type,
 | 
				
			||||||
 | 
													MapType = initAssignExp.Expression.Type
 | 
				
			||||||
							};
 | 
												};
 | 
				
			||||||
							parent.Childs.Add(child);
 | 
												parent.Childs.Add(child);
 | 
				
			||||||
							ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, getSelectGroupingMapString);
 | 
												ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, getSelectGroupingMapString);
 | 
				
			||||||
@@ -107,7 +113,8 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
									var child = new ReadAnonymousTypeInfo {
 | 
														var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
										Property = dtoProp,
 | 
															Property = dtoProp,
 | 
				
			||||||
										CsName = dtoProp.Name,
 | 
															CsName = dtoProp.Name,
 | 
				
			||||||
										CsType = dtoProp.PropertyType
 | 
															CsType = dtoProp.PropertyType,
 | 
				
			||||||
 | 
															MapType = trydtocol.Attribute.MapType
 | 
				
			||||||
									};
 | 
														};
 | 
				
			||||||
									parent.Childs.Add(child);
 | 
														parent.Childs.Add(child);
 | 
				
			||||||
									if (dtTb.Parameter != null)
 | 
														if (dtTb.Parameter != null)
 | 
				
			||||||
@@ -133,7 +140,8 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
							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,
 | 
													CsName = newExp.Members[a].Name,
 | 
				
			||||||
								CsType = newExp.Arguments[a].Type
 | 
													CsType = newExp.Arguments[a].Type,
 | 
				
			||||||
 | 
													MapType = 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);
 | 
				
			||||||
@@ -148,7 +156,8 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
									var child = new ReadAnonymousTypeInfo {
 | 
														var child = new ReadAnonymousTypeInfo {
 | 
				
			||||||
										Property = dtoProp,
 | 
															Property = dtoProp,
 | 
				
			||||||
										CsName = dtoProp.Name,
 | 
															CsName = dtoProp.Name,
 | 
				
			||||||
										CsType = dtoProp.PropertyType
 | 
															CsType = dtoProp.PropertyType,
 | 
				
			||||||
 | 
															MapType = trydtocol.Attribute.MapType
 | 
				
			||||||
									};
 | 
														};
 | 
				
			||||||
									parent.Childs.Add(child);
 | 
														parent.Childs.Add(child);
 | 
				
			||||||
									if (dtTb.Parameter != null)
 | 
														if (dtTb.Parameter != null)
 | 
				
			||||||
@@ -166,7 +175,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					return true;
 | 
										return true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			parent.DbField = $"({ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where)})";
 | 
								parent.DbField = $"({ExpressionLambdaToSql(exp, getTSC())})";
 | 
				
			||||||
			field.Append(", ").Append(parent.DbField);
 | 
								field.Append(", ").Append(parent.DbField);
 | 
				
			||||||
			if (index >= 0) field.Append(" as").Append(++index);
 | 
								if (index >= 0) field.Append(" as").Append(++index);
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
@@ -177,7 +186,9 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
					++index;
 | 
										++index;
 | 
				
			||||||
					return Utils.GetDataReaderValue(parent.CsType, null);
 | 
										return Utils.GetDataReaderValue(parent.CsType, null);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									if (parent.CsType == parent.MapType)
 | 
				
			||||||
					return Utils.GetDataReaderValue(parent.CsType, dr.GetValue(++index));
 | 
										return Utils.GetDataReaderValue(parent.CsType, dr.GetValue(++index));
 | 
				
			||||||
 | 
									return Utils.GetDataReaderValue(parent.CsType, Utils.GetDataReaderValue(parent.MapType, dr.GetValue(++index)));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			switch (parent.ConsturctorType) {
 | 
								switch (parent.ConsturctorType) {
 | 
				
			||||||
				case ReadAnonymousTypeInfoConsturctorType.Arguments:
 | 
									case ReadAnonymousTypeInfoConsturctorType.Arguments:
 | 
				
			||||||
@@ -204,10 +215,25 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal string ExpressionConstant(ConstantExpression exp) => _common.FormatSql("{0}", exp?.Value);
 | 
							internal ColumnInfo SearchColumnByField(List<SelectTableInfo> _tables, TableInfo currentTable, string field) {
 | 
				
			||||||
 | 
								if (_tables != null) {
 | 
				
			||||||
 | 
									var testCol = _common.TrimQuoteSqlName(field).Split(new[] { '.' }, 2);
 | 
				
			||||||
 | 
									if (testCol.Length == 2) {
 | 
				
			||||||
 | 
										var testTb = _tables.Where(a => a.Alias == testCol[0]).ToArray();
 | 
				
			||||||
 | 
										if (testTb.Length == 1 && testTb[0].Table.Columns.TryGetValue(testCol[1], out var trytstcol))
 | 
				
			||||||
 | 
											return trytstcol;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (currentTable != null) {
 | 
				
			||||||
 | 
									var testCol = _common.TrimQuoteSqlName(field);
 | 
				
			||||||
 | 
									if (currentTable.Columns.TryGetValue(testCol, out var trytstcol))
 | 
				
			||||||
 | 
										return trytstcol;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
 | 
							internal string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
 | 
				
			||||||
			return ExpressionLambdaToSql(exp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, false, ExpressionStyle.SelectColumns);
 | 
								return ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = isQuoteName, isDisableDiyParse = false, style = ExpressionStyle.SelectColumns });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List<SelectTableInfo> _tables, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
 | 
							internal string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List<SelectTableInfo> _tables, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
 | 
				
			||||||
@@ -250,9 +276,9 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			{ ExpressionType.Modulo, "%" },
 | 
								{ ExpressionType.Modulo, "%" },
 | 
				
			||||||
			{ ExpressionType.Equal, "=" },
 | 
								{ ExpressionType.Equal, "=" },
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		internal string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
							internal string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, TableInfo table, List<SelectColumnInfo> _selectColumnMap, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
				
			||||||
			var sql = ExpressionLambdaToSql(exp, _tables, _selectColumnMap, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where);
 | 
								var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = table });
 | 
				
			||||||
			switch(sql) {
 | 
								switch (sql) {
 | 
				
			||||||
				case "1":
 | 
									case "1":
 | 
				
			||||||
				case "'t'": return "1=1";
 | 
									case "'t'": return "1=1";
 | 
				
			||||||
				case "0":
 | 
									case "0":
 | 
				
			||||||
@@ -262,7 +288,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
							internal string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
				
			||||||
			var sql = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, SelectTableInfoType.From, true, false, ExpressionStyle.Where);
 | 
								var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where });
 | 
				
			||||||
			switch (sql) {
 | 
								switch (sql) {
 | 
				
			||||||
				case "1":
 | 
									case "1":
 | 
				
			||||||
				case "'t'": return "1=1";
 | 
									case "'t'": return "1=1";
 | 
				
			||||||
@@ -273,7 +299,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		internal void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
							internal void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
 | 
				
			||||||
			var tbidx = _tables.Count;
 | 
								var tbidx = _tables.Count;
 | 
				
			||||||
			var filter = ExpressionLambdaToSql(exp, _tables, null, getSelectGroupingMapString, tbtype, true, false, ExpressionStyle.Where);
 | 
								var filter = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where });
 | 
				
			||||||
			switch (filter) {
 | 
								switch (filter) {
 | 
				
			||||||
				case "1":
 | 
									case "1":
 | 
				
			||||||
				case "'t'": filter = "1=1"; break;
 | 
									case "'t'": filter = "1=1"; break;
 | 
				
			||||||
@@ -300,50 +326,80 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
		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>();
 | 
							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 ExpressionLambdaToSql(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
					
 | 
				
			||||||
 | 
							internal string ExpressionBinary(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc) {
 | 
				
			||||||
 | 
								var left = ExpressionLambdaToSql(leftExp, tsc);
 | 
				
			||||||
 | 
								var leftMapColumn = SearchColumnByField(tsc._tables, tsc.currentTable, left);
 | 
				
			||||||
 | 
								var isLeftMapType = leftMapColumn != null && (leftMapColumn.Attribute.MapType != rightExp.Type || leftMapColumn.CsType != rightExp.Type);
 | 
				
			||||||
 | 
								ColumnInfo rightMapColumn = null;
 | 
				
			||||||
 | 
								var isRightMapType = false;
 | 
				
			||||||
 | 
								if (isLeftMapType) tsc.mapType = leftMapColumn.Attribute.MapType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var right = ExpressionLambdaToSql(rightExp, tsc);
 | 
				
			||||||
 | 
								if (right != "NULL" && isLeftMapType) {
 | 
				
			||||||
 | 
									var enumType = leftMapColumn.CsType.NullableTypeOrThis();
 | 
				
			||||||
 | 
									if (enumType.IsEnum)
 | 
				
			||||||
 | 
										right = formatSql(Enum.Parse(enumType, right.Trim('\'')), leftMapColumn.Attribute.MapType);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (leftMapColumn == null) {
 | 
				
			||||||
 | 
									rightMapColumn = SearchColumnByField(tsc._tables, tsc.currentTable, right);
 | 
				
			||||||
 | 
									isRightMapType = rightMapColumn != null && (rightMapColumn.Attribute.MapType != leftExp.Type || rightMapColumn.CsType != leftExp.Type);
 | 
				
			||||||
 | 
									if (isRightMapType) {
 | 
				
			||||||
 | 
										tsc.mapType = rightMapColumn.Attribute.MapType;
 | 
				
			||||||
 | 
										left = ExpressionLambdaToSql(leftExp, tsc);
 | 
				
			||||||
 | 
										if (left != "NULL" && isRightMapType) {
 | 
				
			||||||
 | 
											var enumType = rightMapColumn.CsType.NullableTypeOrThis();
 | 
				
			||||||
 | 
											if (enumType.IsEnum)
 | 
				
			||||||
 | 
												left = formatSql(Enum.Parse(enumType, left.Trim('\'')), rightMapColumn.Attribute.MapType);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (left == "NULL") {
 | 
				
			||||||
 | 
									var tmp = right;
 | 
				
			||||||
 | 
									right = left;
 | 
				
			||||||
 | 
									left = tmp;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (right == "NULL") oper = oper == "=" ? " IS " : " IS NOT ";
 | 
				
			||||||
 | 
								if (oper == "+" && (leftExp.Type.FullName == "System.String" || rightExp.Type.FullName == "System.String")) return _common.StringConcat(new[] { left, right }, new[] { leftExp.Type, rightExp.Type });
 | 
				
			||||||
 | 
								if (oper == "%") return _common.Mod(left, right, leftExp.Type, rightExp.Type);
 | 
				
			||||||
 | 
								tsc.mapType = null;
 | 
				
			||||||
 | 
								return $"{left} {oper} {right}";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							internal string ExpressionLambdaToSql(Expression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp == null) return "";
 | 
								if (exp == null) return "";
 | 
				
			||||||
			if (isDisableDiyParse == false && _common._orm.Aop.ParseExpression != null) {
 | 
								if (tsc.isDisableDiyParse == false && _common._orm.Aop.ParseExpression != null) {
 | 
				
			||||||
				var args = new AopParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(exp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, true, style));
 | 
									var args = new AopParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(exp, tsc.CloneDisableDiyParse()));
 | 
				
			||||||
				_common._orm.Aop.ParseExpression?.Invoke(this, args);
 | 
									_common._orm.Aop.ParseExpression?.Invoke(this, args);
 | 
				
			||||||
				if (string.IsNullOrEmpty(args.Result) == false) return args.Result;
 | 
									if (string.IsNullOrEmpty(args.Result) == false) return args.Result;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			switch (exp.NodeType) {
 | 
								switch (exp.NodeType) {
 | 
				
			||||||
				case ExpressionType.Not: return $"not({ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)})";
 | 
									case ExpressionType.Not: return $"not({ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc)})";
 | 
				
			||||||
				case ExpressionType.Quote: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
									case ExpressionType.Quote: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc);
 | 
				
			||||||
				case ExpressionType.Lambda: return ExpressionLambdaToSql((exp as LambdaExpression)?.Body, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
									case ExpressionType.Lambda: return ExpressionLambdaToSql((exp as LambdaExpression)?.Body, tsc);
 | 
				
			||||||
				case ExpressionType.TypeAs:
 | 
									case ExpressionType.TypeAs:
 | 
				
			||||||
				case ExpressionType.Convert:
 | 
									case ExpressionType.Convert:
 | 
				
			||||||
					//var othercExp = ExpressionLambdaToSqlOther(exp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
										//var othercExp = ExpressionLambdaToSqlOther(exp, tsc);
 | 
				
			||||||
					//if (string.IsNullOrEmpty(othercExp) == false) return othercExp;
 | 
										//if (string.IsNullOrEmpty(othercExp) == false) return othercExp;
 | 
				
			||||||
					return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
										return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc);
 | 
				
			||||||
				case ExpressionType.Negate:
 | 
									case ExpressionType.Negate:
 | 
				
			||||||
				case ExpressionType.NegateChecked: return "-" + ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
									case ExpressionType.NegateChecked: return "-" + ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc);
 | 
				
			||||||
				case ExpressionType.Constant: return _common.FormatSql("{0}", (exp as ConstantExpression)?.Value);
 | 
									case ExpressionType.Constant: return formatSql((exp as ConstantExpression)?.Value, tsc.mapType);
 | 
				
			||||||
				case ExpressionType.Conditional:
 | 
									case ExpressionType.Conditional:
 | 
				
			||||||
					var condExp = exp as ConditionalExpression;
 | 
										var condExp = exp as ConditionalExpression;
 | 
				
			||||||
					return $"case when {ExpressionLambdaToSql(condExp.Test, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)} then {ExpressionLambdaToSql(condExp.IfTrue, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)} else {ExpressionLambdaToSql(condExp.IfFalse, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)} end";
 | 
										return $"case when {ExpressionLambdaToSql(condExp.Test, tsc)} then {ExpressionLambdaToSql(condExp.IfTrue, tsc)} else {ExpressionLambdaToSql(condExp.IfFalse, tsc)} end";
 | 
				
			||||||
				case ExpressionType.Call:
 | 
									case ExpressionType.Call:
 | 
				
			||||||
					var exp3 = exp as MethodCallExpression;
 | 
										var exp3 = exp as MethodCallExpression;
 | 
				
			||||||
					var callType = exp3.Object?.Type ?? exp3.Method.DeclaringType;
 | 
										var callType = exp3.Object?.Type ?? exp3.Method.DeclaringType;
 | 
				
			||||||
					switch (callType.FullName) {
 | 
										switch (callType.FullName) {
 | 
				
			||||||
						case "System.String": return ExpressionLambdaToSqlCallString(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
											case "System.String": return ExpressionLambdaToSqlCallString(exp3, tsc);
 | 
				
			||||||
						case "System.Math": return ExpressionLambdaToSqlCallMath(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
											case "System.Math": return ExpressionLambdaToSqlCallMath(exp3, tsc);
 | 
				
			||||||
						case "System.DateTime": return ExpressionLambdaToSqlCallDateTime(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
											case "System.DateTime": return ExpressionLambdaToSqlCallDateTime(exp3, tsc);
 | 
				
			||||||
						case "System.TimeSpan": return ExpressionLambdaToSqlCallTimeSpan(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
											case "System.TimeSpan": return ExpressionLambdaToSqlCallTimeSpan(exp3, tsc);
 | 
				
			||||||
						case "System.Convert": return ExpressionLambdaToSqlCallConvert(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
											case "System.Convert": return ExpressionLambdaToSqlCallConvert(exp3, tsc);
 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					if (exp3.Method.Name == "Equals" && exp3.Object != null && exp3.Arguments.Count > 0) {
 | 
					 | 
				
			||||||
						var tmptryoper = "=";
 | 
					 | 
				
			||||||
						var tmpleft = ExpressionLambdaToSql(exp3.Object, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
					 | 
				
			||||||
						var tmpright = ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
					 | 
				
			||||||
						if (tmpleft == "NULL") {
 | 
					 | 
				
			||||||
							var tmp33 = tmpright;
 | 
					 | 
				
			||||||
							tmpright = tmpleft;
 | 
					 | 
				
			||||||
							tmpleft = tmp33;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						if (tmpright == "NULL") tmptryoper = " IS ";
 | 
					 | 
				
			||||||
						return $"{tmpleft} {tmptryoper} {tmpright}";
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										if (exp3.Method.Name == "Equals" && exp3.Object != null && exp3.Arguments.Count > 0)
 | 
				
			||||||
 | 
											return ExpressionBinary("=", exp3.Object, exp3.Arguments[0], tsc);
 | 
				
			||||||
					if (callType.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) {
 | 
										if (callType.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) {
 | 
				
			||||||
						//if (exp3.Type == typeof(string) && exp3.Arguments.Any() && exp3.Arguments[0].NodeType == ExpressionType.Constant) {
 | 
											//if (exp3.Type == typeof(string) && exp3.Arguments.Any() && exp3.Arguments[0].NodeType == ExpressionType.Constant) {
 | 
				
			||||||
						//	switch (exp3.Method.Name) {
 | 
											//	switch (exp3.Method.Name) {
 | 
				
			||||||
@@ -355,10 +411,10 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						//}
 | 
											//}
 | 
				
			||||||
						switch (exp3.Method.Name) {
 | 
											switch (exp3.Method.Name) {
 | 
				
			||||||
							case "Count": return "count(1)";
 | 
												case "Count": return "count(1)";
 | 
				
			||||||
							case "Sum": return $"sum({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)})";
 | 
												case "Sum": return $"sum({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
 | 
				
			||||||
							case "Avg": return $"avg({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)})";
 | 
												case "Avg": return $"avg({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
 | 
				
			||||||
							case "Max": return $"max({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)})";
 | 
												case "Max": return $"max({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
 | 
				
			||||||
							case "Min": return $"min({ExpressionLambdaToSql(exp3.Arguments[0], _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)})";
 | 
												case "Min": return $"min({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if (callType.FullName.StartsWith("FreeSql.ISelect`")) { //子表查询
 | 
										if (callType.FullName.StartsWith("FreeSql.ISelect`")) { //子表查询
 | 
				
			||||||
@@ -409,7 +465,10 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
																var testExecuteExp = asSelectParentExp;
 | 
																					var testExecuteExp = asSelectParentExp;
 | 
				
			||||||
																if (asSelectParentExp.NodeType == ExpressionType.Parameter) //执行leftjoin关联
 | 
																					if (asSelectParentExp.NodeType == ExpressionType.Parameter) //执行leftjoin关联
 | 
				
			||||||
																	testExecuteExp = Expression.Property(testExecuteExp, _common.GetTableByEntity(asSelectParentExp.Type).Properties.First().Value);
 | 
																						testExecuteExp = Expression.Property(testExecuteExp, _common.GetTableByEntity(asSelectParentExp.Type).Properties.First().Value);
 | 
				
			||||||
																asSelectSql = ExpressionLambdaToSql(testExecuteExp, _tables, new List<SelectColumnInfo>(), getSelectGroupingMapString, SelectTableInfoType.LeftJoin, isQuoteName, true, ExpressionStyle.AsSelect);
 | 
																					var tsc2 = tsc.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(new List<SelectColumnInfo>(), tsc.getSelectGroupingMapString, SelectTableInfoType.LeftJoin);
 | 
				
			||||||
 | 
																					tsc2.isDisableDiyParse = true;
 | 
				
			||||||
 | 
																					tsc2.style = ExpressionStyle.AsSelect;
 | 
				
			||||||
 | 
																					asSelectSql = ExpressionLambdaToSql(testExecuteExp, tsc2);
 | 
				
			||||||
															}
 | 
																				}
 | 
				
			||||||
														}
 | 
																			}
 | 
				
			||||||
													}
 | 
																		}
 | 
				
			||||||
@@ -422,8 +481,8 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
									if (fsqlType == null) break;
 | 
														if (fsqlType == null) break;
 | 
				
			||||||
									fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1);
 | 
														fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1);
 | 
				
			||||||
									fsqltables = fsqlType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(fsql) as List<SelectTableInfo>;
 | 
														fsqltables = fsqlType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(fsql) as List<SelectTableInfo>;
 | 
				
			||||||
									//fsqltables[0].Alias = $"{_tables[0].Alias}_{fsqltables[0].Alias}";
 | 
														//fsqltables[0].Alias = $"{tsc._tables[0].Alias}_{fsqltables[0].Alias}";
 | 
				
			||||||
									fsqltables.AddRange(_tables.Select(a => new SelectTableInfo {
 | 
														fsqltables.AddRange(tsc._tables.Select(a => new SelectTableInfo {
 | 
				
			||||||
										Alias = a.Alias,
 | 
															Alias = a.Alias,
 | 
				
			||||||
										On = "1=1",
 | 
															On = "1=1",
 | 
				
			||||||
										Table = a.Table,
 | 
															Table = a.Table,
 | 
				
			||||||
@@ -482,7 +541,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
												typeof(FreeSqlGlobalExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(mfil => mfil.Name == "AsSelect" && mfil.GetParameters().Length == 1).FirstOrDefault()?.MakeGenericMethod(refMiddleEntityType3),
 | 
																	typeof(FreeSqlGlobalExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(mfil => mfil.Name == "AsSelect" && mfil.GetParameters().Length == 1).FirstOrDefault()?.MakeGenericMethod(refMiddleEntityType3),
 | 
				
			||||||
												Expression.Constant(Activator.CreateInstance(typeof(List<>).MakeGenericType(refMiddleEntityType3)))
 | 
																	Expression.Constant(Activator.CreateInstance(typeof(List<>).MakeGenericType(refMiddleEntityType3)))
 | 
				
			||||||
											));
 | 
																));
 | 
				
			||||||
										var manyMainParam = _tables[0].Parameter;
 | 
															var manyMainParam = tsc._tables[0].Parameter;
 | 
				
			||||||
										var manySubSelectWhereParam = Expression.Parameter(parm123Ref.RefMiddleEntityType, $"M{fsqlWhereParam.Name}_M{asSelectParentExp.ToString().Replace(".", "__")}");//, $"{fsqlWhereParam.Name}__");
 | 
															var manySubSelectWhereParam = Expression.Parameter(parm123Ref.RefMiddleEntityType, $"M{fsqlWhereParam.Name}_M{asSelectParentExp.ToString().Replace(".", "__")}");//, $"{fsqlWhereParam.Name}__");
 | 
				
			||||||
										Expression manySubSelectWhereExp = null;
 | 
															Expression manySubSelectWhereExp = null;
 | 
				
			||||||
										for (var mn = 0; mn < parm123Ref.Columns.Count; mn++) {
 | 
															for (var mn = 0; mn < parm123Ref.Columns.Count; mn++) {
 | 
				
			||||||
@@ -528,7 +587,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
										manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectAny);
 | 
															manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectAny);
 | 
				
			||||||
										asSelectBefores.Clear();
 | 
															asSelectBefores.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
										return ExpressionLambdaToSql(manySubSelectExpBoy, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
															return ExpressionLambdaToSql(manySubSelectExpBoy, tsc);
 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
									for (var mn = 0; mn < parm123Ref.Columns.Count; mn++) {
 | 
														for (var mn = 0; mn < parm123Ref.Columns.Count; mn++) {
 | 
				
			||||||
										var col1 = parm123Ref.RefColumns[mn];
 | 
															var col1 = parm123Ref.RefColumns[mn];
 | 
				
			||||||
@@ -559,23 +618,23 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
							
 | 
												
 | 
				
			||||||
					//	}
 | 
										//	}
 | 
				
			||||||
					//}
 | 
										//}
 | 
				
			||||||
					var other3Exp = ExpressionLambdaToSqlOther(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
										var other3Exp = ExpressionLambdaToSqlOther(exp3, tsc);
 | 
				
			||||||
					if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp;
 | 
										if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp;
 | 
				
			||||||
					throw new Exception($"未实现函数表达式 {exp3} 解析");
 | 
										throw new Exception($"未实现函数表达式 {exp3} 解析");
 | 
				
			||||||
				case ExpressionType.Parameter:
 | 
									case ExpressionType.Parameter:
 | 
				
			||||||
				case ExpressionType.MemberAccess:
 | 
									case ExpressionType.MemberAccess:
 | 
				
			||||||
					var exp4 = exp as MemberExpression;
 | 
										var exp4 = exp as MemberExpression;
 | 
				
			||||||
					if (exp4 != null) {
 | 
										if (exp4 != null) {
 | 
				
			||||||
						if (exp4.Expression != null && exp4.Expression.Type.IsArray == false && exp4.Expression.Type.IsNullableType()) return ExpressionLambdaToSql(exp4.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
											if (exp4.Expression != null && exp4.Expression.Type.IsArray == false && exp4.Expression.Type.IsNullableType()) return ExpressionLambdaToSql(exp4.Expression, tsc);
 | 
				
			||||||
						var extRet = "";
 | 
											var extRet = "";
 | 
				
			||||||
						var memberType = exp4.Expression?.Type ?? exp4.Type;
 | 
											var memberType = exp4.Expression?.Type ?? exp4.Type;
 | 
				
			||||||
						switch (memberType.FullName) {
 | 
											switch (memberType.FullName) {
 | 
				
			||||||
							case "System.String": extRet = ExpressionLambdaToSqlMemberAccessString(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style); break;
 | 
												case "System.String": extRet = ExpressionLambdaToSqlMemberAccessString(exp4, tsc); break;
 | 
				
			||||||
							case "System.DateTime": extRet = ExpressionLambdaToSqlMemberAccessDateTime(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style); break;
 | 
												case "System.DateTime": extRet = ExpressionLambdaToSqlMemberAccessDateTime(exp4, tsc); break;
 | 
				
			||||||
							case "System.TimeSpan": extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style); break;
 | 
												case "System.TimeSpan": extRet = ExpressionLambdaToSqlMemberAccessTimeSpan(exp4, tsc); break;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						if (string.IsNullOrEmpty(extRet) == false) return extRet;
 | 
											if (string.IsNullOrEmpty(extRet) == false) return extRet;
 | 
				
			||||||
						var other4Exp = ExpressionLambdaToSqlOther(exp4, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
											var other4Exp = ExpressionLambdaToSqlOther(exp4, tsc);
 | 
				
			||||||
						if (string.IsNullOrEmpty(other4Exp) == false) return other4Exp;
 | 
											if (string.IsNullOrEmpty(other4Exp) == false) return other4Exp;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					var expStack = new Stack<Expression>();
 | 
										var expStack = new Stack<Expression>();
 | 
				
			||||||
@@ -613,67 +672,67 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if (expStack.First().NodeType != ExpressionType.Parameter) return _common.FormatSql("{0}", Expression.Lambda(exp).Compile().DynamicInvoke());
 | 
										if (expStack.First().NodeType != ExpressionType.Parameter) return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType);
 | 
				
			||||||
					if (callExp != null) return ExpressionLambdaToSql(callExp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
										if (callExp != null) return ExpressionLambdaToSql(callExp, tsc);
 | 
				
			||||||
					if (getSelectGroupingMapString != null && expStack.First().Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) {
 | 
										if (tsc.getSelectGroupingMapString != null && expStack.First().Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`")) {
 | 
				
			||||||
						if (getSelectGroupingMapString != null) {
 | 
											if (tsc.getSelectGroupingMapString != null) {
 | 
				
			||||||
							var expText = getSelectGroupingMapString(expStack.Where((a, b) => b >= 2).ToArray());
 | 
												var expText = tsc.getSelectGroupingMapString(expStack.Where((a, b) => b >= 2).ToArray());
 | 
				
			||||||
							if (string.IsNullOrEmpty(expText) == false) return expText;
 | 
												if (string.IsNullOrEmpty(expText) == false) return expText;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (_tables == null) {
 | 
										if (tsc._tables == null) {
 | 
				
			||||||
						var pp = expStack.Pop() as ParameterExpression;
 | 
											var pp = expStack.Pop() as ParameterExpression;
 | 
				
			||||||
						var memberExp = expStack.Pop() as MemberExpression;
 | 
											var memberExp = expStack.Pop() as MemberExpression;
 | 
				
			||||||
						var tb = _common.GetTableByEntity(pp.Type);
 | 
											var tb = _common.GetTableByEntity(pp.Type);
 | 
				
			||||||
						if (tb.ColumnsByCs.ContainsKey(memberExp.Member.Name) == false) throw new ArgumentException($"{tb.DbName} 找不到列 {memberExp.Member.Name}");
 | 
											if (tb.ColumnsByCs.ContainsKey(memberExp.Member.Name) == false) throw new ArgumentException($"{tb.DbName} 找不到列 {memberExp.Member.Name}");
 | 
				
			||||||
						if (_selectColumnMap != null) {
 | 
											if (tsc._selectColumnMap != null) {
 | 
				
			||||||
							_selectColumnMap.Add(new SelectColumnInfo { Table = null, Column = tb.ColumnsByCs[memberExp.Member.Name] });
 | 
												tsc._selectColumnMap.Add(new SelectColumnInfo { Table = null, Column = tb.ColumnsByCs[memberExp.Member.Name] });
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						var name = tb.ColumnsByCs[memberExp.Member.Name].Attribute.Name;
 | 
											var name = tb.ColumnsByCs[memberExp.Member.Name].Attribute.Name;
 | 
				
			||||||
						if (isQuoteName) name = _common.QuoteSqlName(name);
 | 
											if (tsc.isQuoteName) name = _common.QuoteSqlName(name);
 | 
				
			||||||
						return name;
 | 
											return name;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					Func<TableInfo, string, bool, ParameterExpression, MemberExpression, SelectTableInfo> getOrAddTable = (tbtmp, alias, isa, parmExp, mp) => {
 | 
										Func<TableInfo, string, bool, ParameterExpression, MemberExpression, SelectTableInfo> getOrAddTable = (tbtmp, alias, isa, parmExp, mp) => {
 | 
				
			||||||
						var finds = new SelectTableInfo[0];
 | 
											var finds = new SelectTableInfo[0];
 | 
				
			||||||
						if (style == ExpressionStyle.SelectColumns) {
 | 
											if (tsc.style == ExpressionStyle.SelectColumns) {
 | 
				
			||||||
							finds = _tables.Where(a => a.Table.Type == tbtmp.Type).ToArray();
 | 
												finds = tsc._tables.Where(a => a.Table.Type == tbtmp.Type).ToArray();
 | 
				
			||||||
							if (finds.Any()) finds = new[] { finds.First() };
 | 
												if (finds.Any()) finds = new[] { finds.First() };
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						if (finds.Length != 1 && isa && parmExp != null)
 | 
											if (finds.Length != 1 && isa && parmExp != null)
 | 
				
			||||||
							finds = _tables.Where(a => a.Parameter == parmExp).ToArray();
 | 
												finds = tsc._tables.Where(a => a.Parameter == parmExp).ToArray();
 | 
				
			||||||
						if (finds.Length != 1) {
 | 
											if (finds.Length != 1) {
 | 
				
			||||||
							var navdot = string.IsNullOrEmpty(alias) ? new SelectTableInfo[0] : _tables.Where(a2 => a2.Parameter != null && alias.StartsWith($"{a2.Alias}__")).ToArray();
 | 
												var navdot = string.IsNullOrEmpty(alias) ? new SelectTableInfo[0] : tsc._tables.Where(a2 => a2.Parameter != null && alias.StartsWith($"{a2.Alias}__")).ToArray();
 | 
				
			||||||
							if (navdot.Length > 0) {
 | 
												if (navdot.Length > 0) {
 | 
				
			||||||
								var isthis = navdot[0] == _tables[0];
 | 
													var isthis = navdot[0] == tsc._tables[0];
 | 
				
			||||||
								finds = _tables.Where(a2 => (isa && a2.Parameter != null || !isa && a2.Parameter == null) &&
 | 
													finds = tsc._tables.Where(a2 => (isa && a2.Parameter != null || !isa && a2.Parameter == null) &&
 | 
				
			||||||
									a2.Table.Type == tbtmp.Type && a2.Alias == alias && a2.Alias.StartsWith($"{navdot[0].Alias}__") &&
 | 
														a2.Table.Type == tbtmp.Type && a2.Alias == alias && a2.Alias.StartsWith($"{navdot[0].Alias}__") &&
 | 
				
			||||||
									(isthis && a2.Type != SelectTableInfoType.Parent || !isthis && a2.Type == SelectTableInfoType.Parent)).ToArray();
 | 
														(isthis && a2.Type != SelectTableInfoType.Parent || !isthis && a2.Type == SelectTableInfoType.Parent)).ToArray();
 | 
				
			||||||
								if (finds.Length == 0)
 | 
													if (finds.Length == 0)
 | 
				
			||||||
									finds = _tables.Where(a2 => 
 | 
														finds = tsc._tables.Where(a2 => 
 | 
				
			||||||
										 a2.Table.Type == tbtmp.Type && a2.Alias == alias && a2.Alias.StartsWith($"{navdot[0].Alias}__") &&
 | 
															 a2.Table.Type == tbtmp.Type && a2.Alias == alias && a2.Alias.StartsWith($"{navdot[0].Alias}__") &&
 | 
				
			||||||
										 (isthis && a2.Type != SelectTableInfoType.Parent || !isthis && a2.Type == SelectTableInfoType.Parent)).ToArray();
 | 
															 (isthis && a2.Type != SelectTableInfoType.Parent || !isthis && a2.Type == SelectTableInfoType.Parent)).ToArray();
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								finds = _tables.Where(a2 => (isa && a2.Parameter != null || isa && a2.Parameter == null) &&
 | 
													finds = tsc._tables.Where(a2 => (isa && a2.Parameter != null || isa && a2.Parameter == null) &&
 | 
				
			||||||
									a2.Table.Type == tbtmp.Type && a2.Alias == alias).ToArray();
 | 
														a2.Table.Type == tbtmp.Type && a2.Alias == alias).ToArray();
 | 
				
			||||||
								if (finds.Length != 1) {
 | 
													if (finds.Length != 1) {
 | 
				
			||||||
									finds = _tables.Where(a2 => (isa && a2.Parameter != null || isa && a2.Parameter == null) &&
 | 
														finds = tsc._tables.Where(a2 => (isa && a2.Parameter != null || isa && a2.Parameter == null) &&
 | 
				
			||||||
										a2.Table.Type == tbtmp.Type).ToArray();
 | 
															a2.Table.Type == tbtmp.Type).ToArray();
 | 
				
			||||||
									if (finds.Length != 1) {
 | 
														if (finds.Length != 1) {
 | 
				
			||||||
										finds = _tables.Where(a2 => (isa && a2.Parameter != null || isa && a2.Parameter == null) &&
 | 
															finds = tsc._tables.Where(a2 => (isa && a2.Parameter != null || isa && a2.Parameter == null) &&
 | 
				
			||||||
											a2.Table.Type == tbtmp.Type).ToArray();
 | 
																a2.Table.Type == tbtmp.Type).ToArray();
 | 
				
			||||||
										if (finds.Length != 1)
 | 
															if (finds.Length != 1)
 | 
				
			||||||
											finds = _tables.Where(a2 => a2.Table.Type == tbtmp.Type).ToArray();
 | 
																finds = tsc._tables.Where(a2 => a2.Table.Type == tbtmp.Type).ToArray();
 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							//finds = _tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && (isthis && a2.Type != SelectTableInfoType.Parent || !isthis)).ToArray(); //外部表,内部表一起查
 | 
												//finds = tsc._tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && (isthis && a2.Type != SelectTableInfoType.Parent || !isthis)).ToArray(); //外部表,内部表一起查
 | 
				
			||||||
							//if (finds.Length > 1) {
 | 
												//if (finds.Length > 1) {
 | 
				
			||||||
							//	finds = _tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && a2.Type == SelectTableInfoType.Parent && a2.Alias == alias).ToArray(); //查询外部表
 | 
												//	finds = tsc._tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && a2.Type == SelectTableInfoType.Parent && a2.Alias == alias).ToArray(); //查询外部表
 | 
				
			||||||
							//	if (finds.Any() == false) {
 | 
												//	if (finds.Any() == false) {
 | 
				
			||||||
							//		finds = _tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && a2.Type != SelectTableInfoType.Parent).ToArray(); //查询内部表
 | 
												//		finds = tsc._tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && a2.Type != SelectTableInfoType.Parent).ToArray(); //查询内部表
 | 
				
			||||||
							//		if (finds.Length > 1)
 | 
												//		if (finds.Length > 1)
 | 
				
			||||||
							//			finds = _tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && a2.Type != SelectTableInfoType.Parent && a2.Alias == alias).ToArray();
 | 
												//			finds = tsc._tables.Where((a2, c2) => (isa || a2.Parameter == null) && a2.Table.CsName == tbtmp.CsName && a2.Type != SelectTableInfoType.Parent && a2.Alias == alias).ToArray();
 | 
				
			||||||
							//	}
 | 
												//	}
 | 
				
			||||||
							//}
 | 
												//}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
@@ -681,11 +740,11 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						if (find != null && isa && parmExp != null && find.Parameter != parmExp)
 | 
											if (find != null && isa && parmExp != null && find.Parameter != parmExp)
 | 
				
			||||||
							find.Parameter = parmExp;
 | 
												find.Parameter = parmExp;
 | 
				
			||||||
						if (find == null) {
 | 
											if (find == null) {
 | 
				
			||||||
							_tables.Add(find = new SelectTableInfo { Table = tbtmp, Alias = alias, On = null, Type = mp == null ? tbtype : SelectTableInfoType.LeftJoin, Parameter = isa ? parmExp : null });
 | 
												tsc._tables.Add(find = new SelectTableInfo { Table = tbtmp, Alias = alias, On = null, Type = mp == null ? tsc.tbtype : SelectTableInfoType.LeftJoin, Parameter = isa ? parmExp : null });
 | 
				
			||||||
							if (mp?.Expression != null) { //导航条件,OneToOne、ManyToOne
 | 
												if (mp?.Expression != null) { //导航条件,OneToOne、ManyToOne
 | 
				
			||||||
								var firstTb = _tables.First().Table;
 | 
													var firstTb = tsc._tables.First().Table;
 | 
				
			||||||
								var parentTb = _common.GetTableByEntity(mp.Expression.Type);
 | 
													var parentTb = _common.GetTableByEntity(mp.Expression.Type);
 | 
				
			||||||
								var parentTbRef = parentTb.GetTableRef(mp.Member.Name, style == ExpressionStyle.AsSelect);
 | 
													var parentTbRef = parentTb.GetTableRef(mp.Member.Name, tsc.style == ExpressionStyle.AsSelect);
 | 
				
			||||||
								if (parentTbRef != null) {
 | 
													if (parentTbRef != null) {
 | 
				
			||||||
									Expression navCondExp = null;
 | 
														Expression navCondExp = null;
 | 
				
			||||||
									for (var mn = 0; mn < parentTbRef.Columns.Count; mn++) {
 | 
														for (var mn = 0; mn < parentTbRef.Columns.Count; mn++) {
 | 
				
			||||||
@@ -704,9 +763,9 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
									if (find.Type == SelectTableInfoType.InnerJoin ||
 | 
														if (find.Type == SelectTableInfoType.InnerJoin ||
 | 
				
			||||||
										find.Type == SelectTableInfoType.LeftJoin ||
 | 
															find.Type == SelectTableInfoType.LeftJoin ||
 | 
				
			||||||
										find.Type == SelectTableInfoType.RightJoin)
 | 
															find.Type == SelectTableInfoType.RightJoin)
 | 
				
			||||||
										find.On = ExpressionLambdaToSql(navCondExp, _tables, null, null, find.Type, isQuoteName, isDisableDiyParse, style);
 | 
															find.On = ExpressionLambdaToSql(navCondExp, tsc.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(null, null, find.Type));
 | 
				
			||||||
									else
 | 
														else
 | 
				
			||||||
										find.NavigateCondition = ExpressionLambdaToSql(navCondExp, _tables, null, null, find.Type, isQuoteName, isDisableDiyParse, style);
 | 
															find.NavigateCondition = ExpressionLambdaToSql(navCondExp, tsc.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(null, null, find.Type));
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
@@ -740,29 +799,29 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
									tb2 = tb2tmp;
 | 
														tb2 = tb2tmp;
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								if (exp2.NodeType == ExpressionType.Parameter && expStack.Any() == false) { //附加选择的参数所有列
 | 
													if (exp2.NodeType == ExpressionType.Parameter && expStack.Any() == false) { //附加选择的参数所有列
 | 
				
			||||||
									if (_selectColumnMap != null) {
 | 
														if (tsc._selectColumnMap != null) {
 | 
				
			||||||
										foreach (var tb2c in tb2.Columns.Values)
 | 
															foreach (var tb2c in tb2.Columns.Values)
 | 
				
			||||||
											_selectColumnMap.Add(new SelectColumnInfo { Table = find2, Column = tb2c });
 | 
																tsc._selectColumnMap.Add(new SelectColumnInfo { Table = find2, Column = tb2c });
 | 
				
			||||||
										if (tb2.Columns.Any()) return "";
 | 
															if (tb2.Columns.Any()) return "";
 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								if (mp2 == null || expStack.Any()) continue;
 | 
													if (mp2 == null || expStack.Any()) continue;
 | 
				
			||||||
								if (tb2.ColumnsByCs.ContainsKey(mp2.Member.Name) == false) { //如果选的是对象,附加所有列
 | 
													if (tb2.ColumnsByCs.ContainsKey(mp2.Member.Name) == false) { //如果选的是对象,附加所有列
 | 
				
			||||||
									if (_selectColumnMap != null) {
 | 
														if (tsc._selectColumnMap != null) {
 | 
				
			||||||
										var tb3 = _common.GetTableByEntity(mp2.Type);
 | 
															var tb3 = _common.GetTableByEntity(mp2.Type);
 | 
				
			||||||
										if (tb3 != null) {
 | 
															if (tb3 != null) {
 | 
				
			||||||
											var find3 = getOrAddTable(tb2tmp, alias2 /*$"{alias2}__{mp2.Member.Name}"*/, exp2.NodeType == ExpressionType.Parameter, parmExp2, mp2);
 | 
																var find3 = getOrAddTable(tb2tmp, alias2 /*$"{alias2}__{mp2.Member.Name}"*/, exp2.NodeType == ExpressionType.Parameter, parmExp2, mp2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
											foreach (var tb3c in tb3.Columns.Values)
 | 
																foreach (var tb3c in tb3.Columns.Values)
 | 
				
			||||||
												_selectColumnMap.Add(new SelectColumnInfo { Table = find3, Column = tb3c });
 | 
																	tsc._selectColumnMap.Add(new SelectColumnInfo { Table = find3, Column = tb3c });
 | 
				
			||||||
											if (tb3.Columns.Any()) return "";
 | 
																if (tb3.Columns.Any()) return "";
 | 
				
			||||||
										}
 | 
															}
 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
									throw new ArgumentException($"{tb2.DbName} 找不到列 {mp2.Member.Name}");
 | 
														throw new ArgumentException($"{tb2.DbName} 找不到列 {mp2.Member.Name}");
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								var col2 = tb2.ColumnsByCs[mp2.Member.Name];
 | 
													var col2 = tb2.ColumnsByCs[mp2.Member.Name];
 | 
				
			||||||
								if (_selectColumnMap != null && find2 != null) {
 | 
													if (tsc._selectColumnMap != null && find2 != null) {
 | 
				
			||||||
									_selectColumnMap.Add(new SelectColumnInfo { Table = find2, Column = col2 });
 | 
														tsc._selectColumnMap.Add(new SelectColumnInfo { Table = find2, Column = col2 });
 | 
				
			||||||
									return "";
 | 
														return "";
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								name2 = tb2.ColumnsByCs[mp2.Member.Name].Attribute.Name;
 | 
													name2 = tb2.ColumnsByCs[mp2.Member.Name].Attribute.Name;
 | 
				
			||||||
@@ -770,63 +829,78 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
							case ExpressionType.Call:break;
 | 
												case ExpressionType.Call:break;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if (isQuoteName) name2 = _common.QuoteSqlName(name2);
 | 
										if (tsc.isQuoteName) name2 = _common.QuoteSqlName(name2);
 | 
				
			||||||
					return $"{alias2}.{name2}";
 | 
										return $"{alias2}.{name2}";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var expBinary = exp as BinaryExpression;
 | 
								var expBinary = exp as BinaryExpression;
 | 
				
			||||||
			if (expBinary == null) {
 | 
								if (expBinary == null) {
 | 
				
			||||||
				var other99Exp = ExpressionLambdaToSqlOther(exp, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
									var other99Exp = ExpressionLambdaToSqlOther(exp, tsc);
 | 
				
			||||||
				if (string.IsNullOrEmpty(other99Exp) == false) return other99Exp;
 | 
									if (string.IsNullOrEmpty(other99Exp) == false) return other99Exp;
 | 
				
			||||||
				return "";
 | 
									return "";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			switch (expBinary.NodeType) {
 | 
								switch (expBinary.NodeType) {
 | 
				
			||||||
				case ExpressionType.Coalesce:
 | 
									case ExpressionType.Coalesce:
 | 
				
			||||||
					return _common.IsNull(ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style), ExpressionLambdaToSql(expBinary.Right, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style));
 | 
										return _common.IsNull(ExpressionLambdaToSql(expBinary.Left, tsc), ExpressionLambdaToSql(expBinary.Right, tsc));
 | 
				
			||||||
				case ExpressionType.OrElse:
 | 
									case ExpressionType.OrElse:
 | 
				
			||||||
					return $"({ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)} OR {ExpressionLambdaToSql(expBinary.Right, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style)})";
 | 
										return $"({ExpressionLambdaToSql(expBinary.Left, tsc)} OR {ExpressionLambdaToSql(expBinary.Right, tsc)})";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (dicExpressionOperator.TryGetValue(expBinary.NodeType, out var tryoper) == false) return "";
 | 
								if (dicExpressionOperator.TryGetValue(expBinary.NodeType, out var tryoper) == false) return "";
 | 
				
			||||||
			var left = ExpressionLambdaToSql(expBinary.Left, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
					
 | 
				
			||||||
			var right = ExpressionLambdaToSql(expBinary.Right, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								return ExpressionBinary(tryoper, expBinary.Left, expBinary.Right, tsc);
 | 
				
			||||||
			if (left == "NULL") {
 | 
					 | 
				
			||||||
				var tmp = right;
 | 
					 | 
				
			||||||
				right = left;
 | 
					 | 
				
			||||||
				left = tmp;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (right == "NULL") tryoper = tryoper == "=" ? " IS " : " IS NOT ";
 | 
					 | 
				
			||||||
			if (tryoper == "+" && (expBinary.Left.Type.FullName == "System.String" || expBinary.Right.Type.FullName == "System.String")) return _common.StringConcat(new[] { left, right }, new[] { expBinary.Left.Type, expBinary.Right.Type });
 | 
					 | 
				
			||||||
			if (tryoper == "%") return _common.Mod(left, right, expBinary.Left.Type, expBinary.Right.Type);
 | 
					 | 
				
			||||||
			if (_common._orm.Ado.DataType == DataType.MySql) {
 | 
					 | 
				
			||||||
				//处理c#变态enum convert, a.EnumType1 == Xxx.Xxx,被转成了 Convert(a.EnumType1, Int32) == 1
 | 
					 | 
				
			||||||
				if (expBinary.Left.NodeType == ExpressionType.Convert && expBinary.Right.NodeType == ExpressionType.Constant) {
 | 
					 | 
				
			||||||
					if (long.TryParse(right, out var tryenumLong)) {
 | 
					 | 
				
			||||||
						var enumType = (expBinary.Left as UnaryExpression)?.Operand.Type;
 | 
					 | 
				
			||||||
						if (enumType?.IsEnum == true)
 | 
					 | 
				
			||||||
							right = _common.FormatSql("{0}", Enum.Parse(enumType, right));
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else if (expBinary.Left.NodeType == ExpressionType.Constant && expBinary.Right.NodeType == ExpressionType.Convert) {
 | 
					 | 
				
			||||||
					if (long.TryParse(left, out var tryenumLong)) {
 | 
					 | 
				
			||||||
						var enumType = (expBinary.Right as UnaryExpression)?.Operand.Type;
 | 
					 | 
				
			||||||
						if (enumType?.IsEnum == true)
 | 
					 | 
				
			||||||
							left = _common.FormatSql("{0}", Enum.Parse(enumType, left));
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return $"{left} {tryoper} {right}";
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc);
 | 
				
			||||||
		internal abstract string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style);
 | 
							internal abstract string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal enum ExpressionStyle {
 | 
							internal enum ExpressionStyle {
 | 
				
			||||||
			Where, AsSelect, SelectColumns
 | 
								Where, AsSelect, SelectColumns
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							internal class ExpTSC {
 | 
				
			||||||
 | 
								public List<SelectTableInfo> _tables { get; set; }
 | 
				
			||||||
 | 
								public List<SelectColumnInfo> _selectColumnMap { get; set; }
 | 
				
			||||||
 | 
								public Func<Expression[], string> getSelectGroupingMapString { get; set; }
 | 
				
			||||||
 | 
								public SelectTableInfoType tbtype { get; set; }
 | 
				
			||||||
 | 
								public bool isQuoteName { get; set; }
 | 
				
			||||||
 | 
								public bool isDisableDiyParse { get; set; }
 | 
				
			||||||
 | 
								public ExpressionStyle style { get; set; }
 | 
				
			||||||
 | 
								public Type mapType { get; set; }
 | 
				
			||||||
 | 
								public TableInfo currentTable { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								public ExpTSC CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(List<SelectColumnInfo> v1, Func<Expression[], string> v2, SelectTableInfoType v3 ) {
 | 
				
			||||||
 | 
									return new ExpTSC {
 | 
				
			||||||
 | 
										_tables = this._tables,
 | 
				
			||||||
 | 
										_selectColumnMap = v1,
 | 
				
			||||||
 | 
										getSelectGroupingMapString = v2,
 | 
				
			||||||
 | 
										tbtype = v3,
 | 
				
			||||||
 | 
										isQuoteName = this.isQuoteName,
 | 
				
			||||||
 | 
										isDisableDiyParse = this.isDisableDiyParse,
 | 
				
			||||||
 | 
										style = this.style,
 | 
				
			||||||
 | 
										currentTable = this.currentTable
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								public ExpTSC CloneDisableDiyParse() {
 | 
				
			||||||
 | 
									return new ExpTSC {
 | 
				
			||||||
 | 
										_tables = this._tables,
 | 
				
			||||||
 | 
										_selectColumnMap = this._selectColumnMap,
 | 
				
			||||||
 | 
										getSelectGroupingMapString = this.getSelectGroupingMapString,
 | 
				
			||||||
 | 
										tbtype = this.tbtype,
 | 
				
			||||||
 | 
										isQuoteName = this.isQuoteName,
 | 
				
			||||||
 | 
										isDisableDiyParse = false,
 | 
				
			||||||
 | 
										style = this.style,
 | 
				
			||||||
 | 
										currentTable = this.currentTable
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							internal string formatSql(object obj, Type mapType) {
 | 
				
			||||||
 | 
								return string.Concat(_ado.AddslashesProcessParam(obj, mapType));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
using System.Text.RegularExpressions;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Text.RegularExpressions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace FreeSql.Internal.CommonProvider {
 | 
					namespace FreeSql.Internal.CommonProvider {
 | 
				
			||||||
	partial class AdoProvider {
 | 
						partial class AdoProvider {
 | 
				
			||||||
 | 
							public abstract object AddslashesProcessParam(object param, Type mapType);
 | 
				
			||||||
		public abstract object AddslashesProcessParam(object param);
 | 
					 | 
				
			||||||
		public string Addslashes(string filter, params object[] parms) {
 | 
							public string Addslashes(string filter, params object[] parms) {
 | 
				
			||||||
			if (filter == null || parms == null) return string.Empty;
 | 
								if (filter == null || parms == null) return string.Empty;
 | 
				
			||||||
			if (parms.Length == 0) return filter;
 | 
								if (parms.Length == 0) return filter;
 | 
				
			||||||
@@ -11,7 +11,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
			for (int a = 0; a < parms.Length; a++) {
 | 
								for (int a = 0; a < parms.Length; a++) {
 | 
				
			||||||
				if (parms[a] == null)
 | 
									if (parms[a] == null)
 | 
				
			||||||
					filter = Regex.Replace(filter, @"\s*(=|IN)\s*\{" + a + @"\}", " IS {" + a + "}", RegexOptions.IgnoreCase);
 | 
										filter = Regex.Replace(filter, @"\s*(=|IN)\s*\{" + a + @"\}", " IS {" + a + "}", RegexOptions.IgnoreCase);
 | 
				
			||||||
				nparms[a] = AddslashesProcessParam(parms[a]);
 | 
									nparms[a] = AddslashesProcessParam(parms[a], null);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			try { string ret = string.Format(filter, nparms); return ret; } catch { return filter; }
 | 
								try { string ret = string.Format(filter, nparms); return ret; } catch { return filter; }
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,7 +66,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
		public abstract List<T1> ExecuteDeleted();
 | 
							public abstract List<T1> ExecuteDeleted();
 | 
				
			||||||
		public abstract Task<List<T1>> ExecuteDeletedAsync();
 | 
							public abstract Task<List<T1>> ExecuteDeletedAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IDelete<T1> Where(Expression<Func<T1, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, exp?.Body, null));
 | 
							public IDelete<T1> Where(Expression<Func<T1, bool>> exp) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, _table, null, exp?.Body, null));
 | 
				
			||||||
		public IDelete<T1> Where(string sql, object parms = null) {
 | 
							public IDelete<T1> Where(string sql, object parms = null) {
 | 
				
			||||||
			if (string.IsNullOrEmpty(sql)) return this;
 | 
								if (string.IsNullOrEmpty(sql)) return this;
 | 
				
			||||||
			var args = new AopWhereEventArgs(sql, parms);
 | 
								var args = new AopWhereEventArgs(sql, parms);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -387,17 +387,14 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
				foreach (var col in _table.Columns.Values)
 | 
									foreach (var col in _table.Columns.Values)
 | 
				
			||||||
					if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
 | 
										if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
 | 
				
			||||||
						if (colidx2 > 0) sb.Append(", ");
 | 
											if (colidx2 > 0) sb.Append(", ");
 | 
				
			||||||
						object val = null;
 | 
											object val = col.GetMapValue(d);
 | 
				
			||||||
						if (_table.Properties.TryGetValue(col.CsName, out var tryp)) {
 | 
											if (col.Attribute.IsPrimary && col.Attribute.MapType.NullableTypeOrThis() == typeof(Guid) && (val == null || (Guid)val == Guid.Empty))
 | 
				
			||||||
							val = tryp.GetValue(d);
 | 
												col.SetMapValue(d, val = FreeUtil.NewMongodbId());
 | 
				
			||||||
							if (col.Attribute.IsPrimary && (col.CsType == typeof(Guid) || col.CsType == typeof(Guid?))
 | 
					 | 
				
			||||||
								&& (val == null || (Guid)val == Guid.Empty)) tryp.SetValue(d, val = FreeUtil.NewMongodbId());
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						if (_noneParameter)
 | 
											if (_noneParameter)
 | 
				
			||||||
							sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.CsType, val));
 | 
												sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val));
 | 
				
			||||||
						else {
 | 
											else {
 | 
				
			||||||
							sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}")));
 | 
												sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}")));
 | 
				
			||||||
							_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col.CsType, val);
 | 
												_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col.Attribute.MapType, val);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						++colidx2;
 | 
											++colidx2;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -453,7 +453,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
							if (tbiindex > 0 && colidx == 0) field.Append("\r\n");
 | 
												if (tbiindex > 0 && colidx == 0) field.Append("\r\n");
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
											var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
				
			||||||
						field.Append(_commonUtils.QuoteReadColumn(col.CsType, $"{tbi.Alias}.{quoteName}"));
 | 
											field.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"{tbi.Alias}.{quoteName}"));
 | 
				
			||||||
						++index;
 | 
											++index;
 | 
				
			||||||
						if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
											if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
				
			||||||
						else dicfield.Add(quoteName, true);
 | 
											else dicfield.Add(quoteName, true);
 | 
				
			||||||
@@ -505,7 +505,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
					if (tb.Table.ColumnsByCs.TryGetValue(prop.Name, out var col)) { //普通字段
 | 
										if (tb.Table.ColumnsByCs.TryGetValue(prop.Name, out var col)) { //普通字段
 | 
				
			||||||
						if (index > 0) field.Append(", ");
 | 
											if (index > 0) field.Append(", ");
 | 
				
			||||||
						var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
											var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
				
			||||||
						field.Append(_commonUtils.QuoteReadColumn(col.CsType, $"{tb.Alias}.{quoteName}"));
 | 
											field.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"{tb.Alias}.{quoteName}"));
 | 
				
			||||||
						++index;
 | 
											++index;
 | 
				
			||||||
						if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
											if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
				
			||||||
						else dicfield.Add(quoteName, true);
 | 
											else dicfield.Add(quoteName, true);
 | 
				
			||||||
@@ -525,7 +525,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
						foreach (var col2 in tb2.Table.Columns.Values) {
 | 
											foreach (var col2 in tb2.Table.Columns.Values) {
 | 
				
			||||||
							if (index > 0) field.Append(", ");
 | 
												if (index > 0) field.Append(", ");
 | 
				
			||||||
							var quoteName = _commonUtils.QuoteSqlName(col2.Attribute.Name);
 | 
												var quoteName = _commonUtils.QuoteSqlName(col2.Attribute.Name);
 | 
				
			||||||
							field.Append(_commonUtils.QuoteReadColumn(col2.CsType, $"{tb2.Alias}.{quoteName}"));
 | 
												field.Append(_commonUtils.QuoteReadColumn(col2.Attribute.MapType, $"{tb2.Alias}.{quoteName}"));
 | 
				
			||||||
							++index;
 | 
												++index;
 | 
				
			||||||
							++otherindex;
 | 
												++otherindex;
 | 
				
			||||||
							if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
												if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
				
			||||||
@@ -607,7 +607,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
				if (tb.Table.ColumnsByCs.TryGetValue(p.Name, out var col)) { //普通字段
 | 
									if (tb.Table.ColumnsByCs.TryGetValue(p.Name, out var col)) { //普通字段
 | 
				
			||||||
					if (index > 0) field.Append(", ");
 | 
										if (index > 0) field.Append(", ");
 | 
				
			||||||
					var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
										var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
 | 
				
			||||||
					field.Append(_commonUtils.QuoteReadColumn(col.CsType, $"{tb.Alias}.{quoteName}"));
 | 
										field.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"{tb.Alias}.{quoteName}"));
 | 
				
			||||||
					++index;
 | 
										++index;
 | 
				
			||||||
					if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
										if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
				
			||||||
					else dicfield.Add(quoteName, true);
 | 
										else dicfield.Add(quoteName, true);
 | 
				
			||||||
@@ -620,7 +620,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
					foreach (var col2 in tb2.Table.Columns.Values) {
 | 
										foreach (var col2 in tb2.Table.Columns.Values) {
 | 
				
			||||||
						if (index > 0) field.Append(", ");
 | 
											if (index > 0) field.Append(", ");
 | 
				
			||||||
						var quoteName = _commonUtils.QuoteSqlName(col2.Attribute.Name);
 | 
											var quoteName = _commonUtils.QuoteSqlName(col2.Attribute.Name);
 | 
				
			||||||
						field.Append(_commonUtils.QuoteReadColumn(col2.CsType, $"{tb2.Alias}.{quoteName}"));
 | 
											field.Append(_commonUtils.QuoteReadColumn(col2.Attribute.MapType, $"{tb2.Alias}.{quoteName}"));
 | 
				
			||||||
						++index;
 | 
											++index;
 | 
				
			||||||
						if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
											if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
 | 
				
			||||||
						else dicfield.Add(quoteName, true);
 | 
											else dicfield.Add(quoteName, true);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
		string getSelectGroupingMapString(Expression[] members) {
 | 
							string getSelectGroupingMapString(Expression[] members) {
 | 
				
			||||||
			if (members.Any() == false) return _map.DbField;
 | 
								if (members.Any() == false) return _map.DbField;
 | 
				
			||||||
			var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name;
 | 
								var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name;
 | 
				
			||||||
			switch(parentName) {
 | 
								switch (parentName) {
 | 
				
			||||||
				case "Key":
 | 
									case "Key":
 | 
				
			||||||
					var read = _map;
 | 
										var read = _map;
 | 
				
			||||||
					for (var a = 0; a < members.Length; a++) {
 | 
										for (var a = 0; a < members.Length; a++) {
 | 
				
			||||||
@@ -53,7 +53,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
					var parmExp = Expression.Parameter(tb.Table.Type, tb.Alias);
 | 
										var parmExp = Expression.Parameter(tb.Table.Type, tb.Alias);
 | 
				
			||||||
					Expression retExp = parmExp;
 | 
										Expression retExp = parmExp;
 | 
				
			||||||
					for (var a = foridx; a < members.Length; a++) {
 | 
										for (var a = foridx; a < members.Length; a++) {
 | 
				
			||||||
						switch(members[a].NodeType) {
 | 
											switch (members[a].NodeType) {
 | 
				
			||||||
							case ExpressionType.Call:
 | 
												case ExpressionType.Call:
 | 
				
			||||||
								retExp = Expression.Call(retExp, (members[a] as MethodCallExpression).Method);
 | 
													retExp = Expression.Call(retExp, (members[a] as MethodCallExpression).Method);
 | 
				
			||||||
								break;
 | 
													break;
 | 
				
			||||||
@@ -64,7 +64,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
								return null;
 | 
													return null;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return _comonExp.ExpressionLambdaToSql(retExp, _tables, null, null, SelectTableInfoType.From, true, true, CommonExpression.ExpressionStyle.Where);
 | 
										return _comonExp.ExpressionLambdaToSql(retExp, new CommonExpression.ExpTSC { _tables = _tables, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = true, style = CommonExpression.ExpressionStyle.Where });
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -301,10 +301,10 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
			var col = cols.First();
 | 
								var col = cols.First();
 | 
				
			||||||
			_set.Append(", ").Append(_commonUtils.QuoteSqlName(col.Column.Attribute.Name)).Append(" = ");
 | 
								_set.Append(", ").Append(_commonUtils.QuoteSqlName(col.Column.Attribute.Name)).Append(" = ");
 | 
				
			||||||
			if (_noneParameter) {
 | 
								if (_noneParameter) {
 | 
				
			||||||
				_set.Append(_commonUtils.GetNoneParamaterSqlValue(_params, col.Column.CsType, value));
 | 
									_set.Append(_commonUtils.GetNoneParamaterSqlValue(_params, col.Column.Attribute.MapType, value));
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				_set.Append(_commonUtils.QuoteWriteParamter(col.Column.CsType, $"{_commonUtils.QuoteParamterName("p_")}{_params.Count}"));
 | 
									_set.Append(_commonUtils.QuoteWriteParamter(col.Column.Attribute.MapType, $"{_commonUtils.QuoteParamterName("p_")}{_params.Count}"));
 | 
				
			||||||
				_commonUtils.AppendParamter(_params, null, col.Column.CsType, value);
 | 
									_commonUtils.AppendParamter(_params, null, col.Column.Attribute.MapType, value);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			//foreach (var t in _source) Utils.FillPropertyValue(t, tryf.CsName, value);
 | 
								//foreach (var t in _source) Utils.FillPropertyValue(t, tryf.CsName, value);
 | 
				
			||||||
			return this;
 | 
								return this;
 | 
				
			||||||
@@ -313,11 +313,11 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
			if (binaryExpression?.Body is BinaryExpression == false &&
 | 
								if (binaryExpression?.Body is BinaryExpression == false &&
 | 
				
			||||||
				binaryExpression?.Body.NodeType != ExpressionType.Call) return this;
 | 
									binaryExpression?.Body.NodeType != ExpressionType.Call) return this;
 | 
				
			||||||
			var cols = new List<SelectColumnInfo>();
 | 
								var cols = new List<SelectColumnInfo>();
 | 
				
			||||||
			var expt = _commonExpression.ExpressionWhereLambdaNoneForeignObject(null, cols, binaryExpression, null);
 | 
								var expt = _commonExpression.ExpressionWhereLambdaNoneForeignObject(null, _table, cols, binaryExpression, null);
 | 
				
			||||||
			if (cols.Any() == false) return this;
 | 
								if (cols.Any() == false) return this;
 | 
				
			||||||
			foreach (var col in cols) {
 | 
								foreach (var col in cols) {
 | 
				
			||||||
				if (col.Column.Attribute.IsNullable == true && col.Column.CsType.IsNullableType()) {
 | 
									if (col.Column.Attribute.IsNullable == true && col.Column.Attribute.MapType.IsNullableType()) {
 | 
				
			||||||
					var replval = _orm.CodeFirst.GetDbInfo(col.Column.CsType.GenericTypeArguments.FirstOrDefault())?.defaultValue;
 | 
										var replval = _orm.CodeFirst.GetDbInfo(col.Column.Attribute.MapType.GenericTypeArguments.FirstOrDefault())?.defaultValue;
 | 
				
			||||||
					if (replval == null) continue;
 | 
										if (replval == null) continue;
 | 
				
			||||||
					var replname = _commonUtils.QuoteSqlName(col.Column.Attribute.Name);
 | 
										var replname = _commonUtils.QuoteSqlName(col.Column.Attribute.Name);
 | 
				
			||||||
					expt = expt.Replace(replname, _commonUtils.IsNull(replname, _commonUtils.FormatSql("{0}", replval)));
 | 
										expt = expt.Replace(replname, _commonUtils.IsNull(replname, _commonUtils.FormatSql("{0}", replval)));
 | 
				
			||||||
@@ -333,7 +333,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
			return this;
 | 
								return this;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public IUpdate<T1> Where(Expression<Func<T1, bool>> expression) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, expression?.Body, null));
 | 
							public IUpdate<T1> Where(Expression<Func<T1, bool>> expression) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, _table, null, expression?.Body, null));
 | 
				
			||||||
		public IUpdate<T1> Where(string sql, object parms = null) {
 | 
							public IUpdate<T1> Where(string sql, object parms = null) {
 | 
				
			||||||
			if (string.IsNullOrEmpty(sql)) return this;
 | 
								if (string.IsNullOrEmpty(sql)) return this;
 | 
				
			||||||
			var args = new AopWhereEventArgs(sql, parms);
 | 
								var args = new AopWhereEventArgs(sql, parms);
 | 
				
			||||||
@@ -361,8 +361,7 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
				var sb = new StringBuilder();
 | 
									var sb = new StringBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
 | 
									sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
 | 
				
			||||||
				var value = _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(_source.First()) : DBNull.Value;
 | 
									sb.Append(thenValue(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, col.GetMapValue(_source.First()))));
 | 
				
			||||||
				sb.Append(thenValue(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.CsType, value)));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				return sb.ToString();
 | 
									return sb.ToString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -382,8 +381,8 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
					cwsb.Append(" \r\nWHEN ");
 | 
										cwsb.Append(" \r\nWHEN ");
 | 
				
			||||||
					ToSqlWhen(cwsb, _table.Primarys, d);
 | 
										ToSqlWhen(cwsb, _table.Primarys, d);
 | 
				
			||||||
					cwsb.Append(" THEN ");
 | 
										cwsb.Append(" THEN ");
 | 
				
			||||||
					var value = _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : DBNull.Value;
 | 
										var value = col.GetMapValue(d);
 | 
				
			||||||
					cwsb.Append(thenValue(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.CsType, value)));
 | 
										cwsb.Append(thenValue(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, value)));
 | 
				
			||||||
					if (isnull == false) isnull = value == null || value == DBNull.Value;
 | 
										if (isnull == false) isnull = value == null || value == DBNull.Value;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				cwsb.Append(" END");
 | 
									cwsb.Append(" END");
 | 
				
			||||||
@@ -427,12 +426,12 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
					if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && _ignore.ContainsKey(col.CsName) == false) {
 | 
										if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && _ignore.ContainsKey(col.CsName) == false) {
 | 
				
			||||||
						if (colidx > 0) sb.Append(", ");
 | 
											if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
						sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
 | 
											sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
 | 
				
			||||||
						var value = _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(_source.First()) : null;
 | 
											var value = col.GetMapValue(_source.First());
 | 
				
			||||||
						if (_noneParameter) {
 | 
											if (_noneParameter) {
 | 
				
			||||||
							sb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.CsType, value));
 | 
												sb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, value));
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
 | 
												sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
 | 
				
			||||||
							_commonUtils.AppendParamter(_paramsSource, null, col.CsType, value);
 | 
												_commonUtils.AppendParamter(_paramsSource, null, col.Attribute.MapType, value);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						++colidx;
 | 
											++colidx;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -460,12 +459,12 @@ namespace FreeSql.Internal.CommonProvider {
 | 
				
			|||||||
							cwsb.Append(" \r\nWHEN ");
 | 
												cwsb.Append(" \r\nWHEN ");
 | 
				
			||||||
							ToSqlWhen(cwsb, _table.Primarys, d);
 | 
												ToSqlWhen(cwsb, _table.Primarys, d);
 | 
				
			||||||
							cwsb.Append(" THEN ");
 | 
												cwsb.Append(" THEN ");
 | 
				
			||||||
							var value = _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : DBNull.Value;
 | 
												var value = col.GetMapValue(d);
 | 
				
			||||||
							if (_noneParameter) {
 | 
												if (_noneParameter) {
 | 
				
			||||||
								cwsb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.CsType, value));
 | 
													cwsb.Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, col.Attribute.MapType, value));
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								cwsb.Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
 | 
													cwsb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
 | 
				
			||||||
								_commonUtils.AppendParamter(_paramsSource, null, col.CsType, value);
 | 
													_commonUtils.AppendParamter(_paramsSource, null, col.Attribute.MapType, value);
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							if (isnull == false) isnull = value == null || value == DBNull.Value;
 | 
												if (isnull == false) isnull = value == null || value == DBNull.Value;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
		internal abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
 | 
							internal abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
 | 
				
			||||||
		internal abstract string FormatSql(string sql, params object[] args);
 | 
							internal abstract string FormatSql(string sql, params object[] args);
 | 
				
			||||||
		internal abstract string QuoteSqlName(string name);
 | 
							internal abstract string QuoteSqlName(string name);
 | 
				
			||||||
 | 
							internal abstract string TrimQuoteSqlName(string name);
 | 
				
			||||||
		internal abstract string QuoteParamterName(string name);
 | 
							internal abstract string QuoteParamterName(string name);
 | 
				
			||||||
		internal abstract string IsNull(string sql, object value);
 | 
							internal abstract string IsNull(string sql, object value);
 | 
				
			||||||
		internal abstract string StringConcat(string[] objs, Type[] types);
 | 
							internal abstract string StringConcat(string[] objs, Type[] types);
 | 
				
			||||||
@@ -100,6 +101,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
				if (trycol._IsNullable != null) attr._IsNullable = trycol.IsNullable;
 | 
									if (trycol._IsNullable != null) attr._IsNullable = trycol.IsNullable;
 | 
				
			||||||
				if (trycol._IsIgnore != null) attr._IsIgnore = trycol.IsIgnore;
 | 
									if (trycol._IsIgnore != null) attr._IsIgnore = trycol.IsIgnore;
 | 
				
			||||||
				if (trycol._IsVersion != null) attr._IsVersion = trycol.IsVersion;
 | 
									if (trycol._IsVersion != null) attr._IsVersion = trycol.IsVersion;
 | 
				
			||||||
 | 
									if (trycol.MapType != null) attr.MapType = trycol.MapType;
 | 
				
			||||||
				if (trycol.DbDefautValue != null) attr.DbDefautValue = trycol.DbDefautValue;
 | 
									if (trycol.DbDefautValue != null) attr.DbDefautValue = trycol.DbDefautValue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var attrs = proto.GetCustomAttributes(typeof(ColumnAttribute), false);
 | 
								var attrs = proto.GetCustomAttributes(typeof(ColumnAttribute), false);
 | 
				
			||||||
@@ -114,34 +116,38 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
				if (tryattr._IsNullable != null) attr._IsNullable = tryattr.IsNullable;
 | 
									if (tryattr._IsNullable != null) attr._IsNullable = tryattr.IsNullable;
 | 
				
			||||||
				if (tryattr._IsIgnore != null) attr._IsIgnore = tryattr.IsIgnore;
 | 
									if (tryattr._IsIgnore != null) attr._IsIgnore = tryattr.IsIgnore;
 | 
				
			||||||
				if (tryattr._IsVersion != null) attr._IsVersion = tryattr.IsVersion;
 | 
									if (tryattr._IsVersion != null) attr._IsVersion = tryattr.IsVersion;
 | 
				
			||||||
 | 
									if (tryattr.MapType != null) attr.MapType = tryattr.MapType;
 | 
				
			||||||
				if (tryattr.DbDefautValue != null) attr.DbDefautValue = tryattr.DbDefautValue;
 | 
									if (tryattr.DbDefautValue != null) attr.DbDefautValue = tryattr.DbDefautValue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (!string.IsNullOrEmpty(attr.Name)) return attr;
 | 
								ColumnAttribute ret = null;
 | 
				
			||||||
			if (!string.IsNullOrEmpty(attr.OldName)) return attr;
 | 
								if (!string.IsNullOrEmpty(attr.Name)) ret = attr;
 | 
				
			||||||
			if (!string.IsNullOrEmpty(attr.DbType)) return attr;
 | 
								if (!string.IsNullOrEmpty(attr.OldName)) ret = attr;
 | 
				
			||||||
			if (attr._IsPrimary != null) return attr;
 | 
								if (!string.IsNullOrEmpty(attr.DbType)) ret = attr;
 | 
				
			||||||
			if (attr._IsIdentity != null) return attr;
 | 
								if (attr._IsPrimary != null) ret = attr;
 | 
				
			||||||
			if (attr._IsNullable != null) return attr;
 | 
								if (attr._IsIdentity != null) ret = attr;
 | 
				
			||||||
			if (attr._IsIgnore != null) return attr;
 | 
								if (attr._IsNullable != null) ret = attr;
 | 
				
			||||||
			if (attr._IsVersion != null) return attr;
 | 
								if (attr._IsIgnore != null) ret = attr;
 | 
				
			||||||
			if (attr.DbDefautValue != null) return attr;
 | 
								if (attr._IsVersion != null) ret = attr;
 | 
				
			||||||
			return null;
 | 
								if (attr.MapType != null) ret = attr;
 | 
				
			||||||
 | 
								if (attr.DbDefautValue != null) ret = attr;
 | 
				
			||||||
 | 
								if (ret != null && ret.MapType == null) ret.MapType = proto.PropertyType;
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal string WhereObject(TableInfo table, string aliasAndDot, object dywhere) {
 | 
							internal string WhereObject(TableInfo table, string aliasAndDot, object dywhere) {
 | 
				
			||||||
			if (dywhere == null) return "";
 | 
								if (dywhere == null) return "";
 | 
				
			||||||
			var type = dywhere.GetType();
 | 
								var type = dywhere.GetType();
 | 
				
			||||||
			var primarys = table.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
 | 
								var primarys = table.Primarys;
 | 
				
			||||||
			if (primarys.Length == 1 && (type == primarys.First().CsType || type.IsNumberType() && primarys.First().CsType.IsNumberType())) {
 | 
								var pk1 = primarys.FirstOrDefault();
 | 
				
			||||||
				return $"{aliasAndDot}{this.QuoteSqlName(primarys.First().Attribute.Name)} = {this.FormatSql("{0}", dywhere)}";
 | 
								if (primarys.Length == 1 && (type == pk1.CsType || type.IsNumberType() && pk1.CsType.IsNumberType())) {
 | 
				
			||||||
 | 
									return $"{aliasAndDot}{this.QuoteSqlName(pk1.Attribute.Name)} = {this.FormatSql("{0}", Utils.GetDataReaderValue(pk1.Attribute.MapType, dywhere))}";
 | 
				
			||||||
			} else if (primarys.Length > 0 && (type == table.Type || type.BaseType == table.Type)) {
 | 
								} else if (primarys.Length > 0 && (type == table.Type || type.BaseType == table.Type)) {
 | 
				
			||||||
				var sb = new StringBuilder();
 | 
									var sb = new StringBuilder();
 | 
				
			||||||
				var pkidx = 0;
 | 
									var pkidx = 0;
 | 
				
			||||||
				foreach (var pk in primarys) {
 | 
									foreach (var pk in primarys) {
 | 
				
			||||||
					var prop = type.GetProperty(pk.CsName, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
 | 
					 | 
				
			||||||
					if (pkidx > 0) sb.Append(" AND ");
 | 
										if (pkidx > 0) sb.Append(" AND ");
 | 
				
			||||||
					sb.Append(aliasAndDot).Append(this.QuoteSqlName(pk.Attribute.Name));
 | 
										sb.Append(aliasAndDot).Append(this.QuoteSqlName(pk.Attribute.Name));
 | 
				
			||||||
					sb.Append(this.FormatSql(" = {0}", prop.GetValue(dywhere)));
 | 
										sb.Append(this.FormatSql(" = {0}", pk.GetMapValue(dywhere)));
 | 
				
			||||||
					++pkidx;
 | 
										++pkidx;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return sb.ToString();
 | 
									return sb.ToString();
 | 
				
			||||||
@@ -165,7 +171,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
					if (table.Columns.TryGetValue(p.Name, out var trycol) == false) continue;
 | 
										if (table.Columns.TryGetValue(p.Name, out var trycol) == false) continue;
 | 
				
			||||||
					if (psidx > 0) sb.Append(" AND ");
 | 
										if (psidx > 0) sb.Append(" AND ");
 | 
				
			||||||
					sb.Append(aliasAndDot).Append(this.QuoteSqlName(trycol.Attribute.Name));
 | 
										sb.Append(aliasAndDot).Append(this.QuoteSqlName(trycol.Attribute.Name));
 | 
				
			||||||
					sb.Append(this.FormatSql(" = {0}", p.GetValue(dywhere)));
 | 
										sb.Append(this.FormatSql(" = {0}", Utils.GetDataReaderValue(trycol.Attribute.MapType, p.GetValue(dywhere))));
 | 
				
			||||||
					++psidx;
 | 
										++psidx;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (psidx == 0) return "";
 | 
									if (psidx == 0) return "";
 | 
				
			||||||
@@ -178,14 +184,14 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			if (table.Primarys.Any() == false) return null;
 | 
								if (table.Primarys.Any() == false) return null;
 | 
				
			||||||
			var its = items.Where(a => a != null).ToArray();
 | 
								var its = items.Where(a => a != null).ToArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var pk1 = table.Primarys.FirstOrDefault();
 | 
				
			||||||
			if (table.Primarys.Length == 1) {
 | 
								if (table.Primarys.Length == 1) {
 | 
				
			||||||
				var sbin = new StringBuilder();
 | 
									var sbin = new StringBuilder();
 | 
				
			||||||
				sbin.Append(aliasAndDot).Append(this.QuoteSqlName(table.Primarys.First().Attribute.Name));
 | 
									sbin.Append(aliasAndDot).Append(this.QuoteSqlName(pk1.Attribute.Name));
 | 
				
			||||||
				var indt = its.Select(a => /*this.FormatSql("{0}", _orm.GetEntityKeyValues(a))*/
 | 
									var indt = its.Select(a => pk1.GetMapValue(a)).Where(a => a != null).ToArray();
 | 
				
			||||||
					table.Properties.TryGetValue(table.Primarys.First().CsName, out var trycol) ? this.FormatSql("{0}", trycol.GetValue(a)) : null).Where(a => a != null).ToArray();
 | 
					 | 
				
			||||||
				if (indt.Any() == false) return null;
 | 
									if (indt.Any() == false) return null;
 | 
				
			||||||
				if (indt.Length == 1) sbin.Append(" = ").Append(indt.First());
 | 
									if (indt.Length == 1) sbin.Append(" = ").Append(this.FormatSql("{0}", indt.First()));
 | 
				
			||||||
				else sbin.Append(" IN (").Append(string.Join(",", indt)).Append(")");
 | 
									else sbin.Append(" IN (").Append(string.Join(",", indt.Select(a => this.FormatSql("{0}", a)))).Append(")");
 | 
				
			||||||
				return sbin.ToString();
 | 
									return sbin.ToString();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var dicpk = its.Length > 5 ? new Dictionary<string, bool>() : null;
 | 
								var dicpk = its.Length > 5 ? new Dictionary<string, bool>() : null;
 | 
				
			||||||
@@ -193,10 +199,8 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			var iidx = 0;
 | 
								var iidx = 0;
 | 
				
			||||||
			foreach (var item in its) {
 | 
								foreach (var item in its) {
 | 
				
			||||||
				var filter = "";
 | 
									var filter = "";
 | 
				
			||||||
				for (var a = 0; a < table.Primarys.Length; a++) {
 | 
									foreach (var pk in table.Primarys)
 | 
				
			||||||
					if (table.Properties.TryGetValue(table.Primarys[a].CsName, out var trycol) == false) continue;
 | 
										filter += $" AND {aliasAndDot}{this.QuoteSqlName(pk.Attribute.Name)} = {this.FormatSql("{0}", pk.GetMapValue(item))}";
 | 
				
			||||||
					filter += $" AND {aliasAndDot}{this.QuoteSqlName(table.Primarys[a].Attribute.Name)} = {this.FormatSql("{0}", trycol.GetValue(item))}";
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (string.IsNullOrEmpty(filter)) continue;
 | 
									if (string.IsNullOrEmpty(filter)) continue;
 | 
				
			||||||
				if (sb != null) {
 | 
									if (sb != null) {
 | 
				
			||||||
					sb.Append(" OR (");
 | 
										sb.Append(" OR (");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,8 @@
 | 
				
			|||||||
using FreeSql.DataAnnotations;
 | 
					using FreeSql.DataAnnotations;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Concurrent;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq.Expressions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace FreeSql.Internal.Model {
 | 
					namespace FreeSql.Internal.Model {
 | 
				
			||||||
	public class ColumnInfo {
 | 
						public class ColumnInfo {
 | 
				
			||||||
@@ -7,5 +10,64 @@ namespace FreeSql.Internal.Model {
 | 
				
			|||||||
		public string CsName { get; set; }
 | 
							public string CsName { get; set; }
 | 
				
			||||||
		public Type CsType { get; set; }
 | 
							public Type CsType { get; set; }
 | 
				
			||||||
		public ColumnAttribute Attribute { get; set; }
 | 
							public ColumnAttribute Attribute { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static ConcurrentDictionary<ColumnInfo, Func<object, object>> _dicGetMapValue = new ConcurrentDictionary<ColumnInfo, Func<object, object>>();
 | 
				
			||||||
 | 
							public object GetMapValue(object obj) {
 | 
				
			||||||
 | 
								var func = _dicGetMapValue.GetOrAdd(this, col => {
 | 
				
			||||||
 | 
									var paramExp = Expression.Parameter(typeof(object));
 | 
				
			||||||
 | 
									var returnTarget = Expression.Label(typeof(object));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (Attribute.MapType == CsType)
 | 
				
			||||||
 | 
										return Expression.Lambda<Func<object, object>>(
 | 
				
			||||||
 | 
											Expression.Block(
 | 
				
			||||||
 | 
												Expression.Return(returnTarget, Expression.Convert(
 | 
				
			||||||
 | 
													Expression.MakeMemberAccess(
 | 
				
			||||||
 | 
														Expression.TypeAs(paramExp, col.Table.Type),
 | 
				
			||||||
 | 
														Table.Properties[col.CsName]
 | 
				
			||||||
 | 
													), typeof(object))),
 | 
				
			||||||
 | 
												Expression.Label(returnTarget, Expression.Default(typeof(object)))
 | 
				
			||||||
 | 
											), new[] { paramExp }).Compile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									var retExp = Expression.Variable(typeof(object), "ret");
 | 
				
			||||||
 | 
									var blockExp = new List<Expression>();
 | 
				
			||||||
 | 
									blockExp.AddRange(new Expression[] {
 | 
				
			||||||
 | 
										Expression.Assign(retExp, Utils.GetDataReaderValueBlockExpression(Attribute.MapType,
 | 
				
			||||||
 | 
											Expression.MakeMemberAccess(
 | 
				
			||||||
 | 
												Expression.TypeAs(paramExp, col.Table.Type),
 | 
				
			||||||
 | 
												Table.Properties[col.CsName]
 | 
				
			||||||
 | 
											)
 | 
				
			||||||
 | 
										)),
 | 
				
			||||||
 | 
										Expression.Return(returnTarget, retExp),
 | 
				
			||||||
 | 
										Expression.Label(returnTarget, Expression.Default(typeof(object)))
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
									return Expression.Lambda<Func<object, object>>(Expression.Block(new[] { retExp }, blockExp), new[] { paramExp }).Compile();
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								return func(obj);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							static ConcurrentDictionary<ColumnInfo, Action<object, object>> _dicSetMapValue = new ConcurrentDictionary<ColumnInfo, Action<object, object>>();
 | 
				
			||||||
 | 
							public void SetMapValue(object obj, object val) {
 | 
				
			||||||
 | 
								var func = _dicSetMapValue.GetOrAdd(this, col => {
 | 
				
			||||||
 | 
									var objExp = Expression.Parameter(typeof(object), "obj");
 | 
				
			||||||
 | 
									var valExp = Expression.Parameter(typeof(object), "val");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (Attribute.MapType == CsType)
 | 
				
			||||||
 | 
										return Expression.Lambda<Action<object, object>>(
 | 
				
			||||||
 | 
											Expression.Assign(Expression.MakeMemberAccess(
 | 
				
			||||||
 | 
												Expression.TypeAs(objExp, col.Table.Type),
 | 
				
			||||||
 | 
												Table.Properties[col.CsName]
 | 
				
			||||||
 | 
											), Expression.Convert(
 | 
				
			||||||
 | 
												valExp, 
 | 
				
			||||||
 | 
												Attribute.MapType)), objExp, valExp).Compile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return Expression.Lambda<Action<object, object>>(
 | 
				
			||||||
 | 
										Expression.Assign(Expression.MakeMemberAccess(
 | 
				
			||||||
 | 
											Expression.TypeAs(objExp, col.Table.Type),
 | 
				
			||||||
 | 
											Table.Properties[col.CsName]
 | 
				
			||||||
 | 
										), Expression.Convert(
 | 
				
			||||||
 | 
											Utils.GetDataReaderValueBlockExpression(Attribute.MapType, valExp), 
 | 
				
			||||||
 | 
											Attribute.MapType)), objExp, valExp).Compile();
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								func(obj, val);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -8,6 +8,7 @@ namespace FreeSql.Internal.Model {
 | 
				
			|||||||
		public PropertyInfo Property { get; set; }
 | 
							public PropertyInfo Property { get; set; }
 | 
				
			||||||
		public string CsName { get; set; }
 | 
							public string CsName { get; set; }
 | 
				
			||||||
		public Type CsType { get; set; }
 | 
							public Type CsType { get; set; }
 | 
				
			||||||
 | 
							public Type MapType { get; set; }
 | 
				
			||||||
		public string DbField { get; set; }
 | 
							public string DbField { get; set; }
 | 
				
			||||||
		public ConstructorInfo Consturctor { get; set; }
 | 
							public ConstructorInfo Consturctor { get; set; }
 | 
				
			||||||
		public ReadAnonymousTypeInfoConsturctorType ConsturctorType { get; set; }
 | 
							public ReadAnonymousTypeInfoConsturctorType ConsturctorType { get; set; }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ using System.Collections.Generic;
 | 
				
			|||||||
using System.Data.Common;
 | 
					using System.Data.Common;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Linq.Expressions;
 | 
					using System.Linq.Expressions;
 | 
				
			||||||
 | 
					using System.Numerics;
 | 
				
			||||||
using System.Reflection;
 | 
					using System.Reflection;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using System.Text.RegularExpressions;
 | 
					using System.Text.RegularExpressions;
 | 
				
			||||||
@@ -22,7 +23,11 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			if (tbc.TryRemove(entity, out var trytb) && trytb?.TypeLazy != null) tbc.TryRemove(trytb.TypeLazy, out var trylz);
 | 
								if (tbc.TryRemove(entity, out var trytb) && trytb?.TypeLazy != null) tbc.TryRemove(trytb.TypeLazy, out var trylz);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
 | 
							internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
 | 
				
			||||||
			if (entity.FullName.StartsWith("<>f__AnonymousType")) return null;
 | 
								if (entity.FullName.StartsWith("<>f__AnonymousType") ||
 | 
				
			||||||
 | 
									entity.IsValueType || 
 | 
				
			||||||
 | 
									entity.IsNullableType() || 
 | 
				
			||||||
 | 
									entity.NullableTypeOrThis() == typeof(BigInteger)
 | 
				
			||||||
 | 
									) return null;
 | 
				
			||||||
			var tbc = _cacheGetTableByEntity.GetOrAdd(common._orm.Ado.DataType, k1 => new ConcurrentDictionary<Type, TableInfo>()); //区分数据库类型缓存
 | 
								var tbc = _cacheGetTableByEntity.GetOrAdd(common._orm.Ado.DataType, k1 => new ConcurrentDictionary<Type, TableInfo>()); //区分数据库类型缓存
 | 
				
			||||||
			if (tbc.TryGetValue(entity, out var trytb)) return trytb;
 | 
								if (tbc.TryGetValue(entity, out var trytb)) return trytb;
 | 
				
			||||||
			if (common.CodeFirst.GetDbInfo(entity) != null) return null;
 | 
								if (common.CodeFirst.GetDbInfo(entity) != null) return null;
 | 
				
			||||||
@@ -49,9 +54,9 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			var propsNavObjs = new List<PropertyInfo>();
 | 
								var propsNavObjs = new List<PropertyInfo>();
 | 
				
			||||||
			foreach (var p in trytb.Properties.Values) {
 | 
								foreach (var p in trytb.Properties.Values) {
 | 
				
			||||||
				var setMethod = trytb.Type.GetMethod($"set_{p.Name}");
 | 
									var setMethod = trytb.Type.GetMethod($"set_{p.Name}");
 | 
				
			||||||
				var tp = common.CodeFirst.GetDbInfo(p.PropertyType);
 | 
					 | 
				
			||||||
				//if (tp == null) continue;
 | 
					 | 
				
			||||||
				var colattr = common.GetEntityColumnAttribute(entity, p);
 | 
									var colattr = common.GetEntityColumnAttribute(entity, p);
 | 
				
			||||||
 | 
									var tp = common.CodeFirst.GetDbInfo(colattr?.MapType ?? p.PropertyType);
 | 
				
			||||||
 | 
									//if (tp == null) continue;
 | 
				
			||||||
				if (tp == null && colattr == null) {
 | 
									if (tp == null && colattr == null) {
 | 
				
			||||||
					if (common.CodeFirst.IsLazyLoading) {
 | 
										if (common.CodeFirst.IsLazyLoading) {
 | 
				
			||||||
						var getIsVirtual = trytb.Type.GetMethod($"get_{p.Name}")?.IsVirtual;
 | 
											var getIsVirtual = trytb.Type.GetMethod($"get_{p.Name}")?.IsVirtual;
 | 
				
			||||||
@@ -69,8 +74,10 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						IsIdentity = false,
 | 
											IsIdentity = false,
 | 
				
			||||||
						IsNullable = tp.Value.isnullable ?? true,
 | 
											IsNullable = tp.Value.isnullable ?? true,
 | 
				
			||||||
						IsPrimary = false,
 | 
											IsPrimary = false,
 | 
				
			||||||
						IsIgnore = false
 | 
											IsIgnore = false,
 | 
				
			||||||
 | 
											MapType = p.PropertyType
 | 
				
			||||||
					};
 | 
										};
 | 
				
			||||||
 | 
									if (colattr._IsNullable == null) colattr._IsNullable = tp.Value.isnullable;
 | 
				
			||||||
				if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)";
 | 
									if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)";
 | 
				
			||||||
				colattr.DbType = colattr.DbType.ToUpper();
 | 
									colattr.DbType = colattr.DbType.ToUpper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -92,10 +99,11 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
					return tmpLt;
 | 
										return tmpLt;
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
				colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type));
 | 
									colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type));
 | 
				
			||||||
 | 
									if (colattr.DbDefautValue != null && p.PropertyType != colattr.MapType) colattr.DbDefautValue = Utils.GetDataReaderValue(colattr.MapType, colattr.DbDefautValue);
 | 
				
			||||||
				if (colattr.DbDefautValue == null) colattr.DbDefautValue = tp?.defaultValue;
 | 
									if (colattr.DbDefautValue == null) colattr.DbDefautValue = tp?.defaultValue;
 | 
				
			||||||
				if (colattr.IsNullable == false && colattr.DbDefautValue == null)
 | 
									if (colattr.IsNullable == false && colattr.DbDefautValue == null)
 | 
				
			||||||
					colattr.DbDefautValue = Activator.CreateInstance(p.PropertyType.IsNullableType() ? p.PropertyType.GenericTypeArguments.FirstOrDefault() : p.PropertyType);
 | 
										colattr.DbDefautValue = Activator.CreateInstance(colattr.MapType.IsNullableType() ? colattr.MapType.GenericTypeArguments.FirstOrDefault() : colattr.MapType);
 | 
				
			||||||
				if (colattr.IsIdentity == true && p.PropertyType.IsNumberType() == false)
 | 
									if (colattr.IsIdentity == true && colattr.MapType.IsNumberType() == false)
 | 
				
			||||||
					colattr.IsIdentity = false;
 | 
										colattr.IsIdentity = false;
 | 
				
			||||||
				if (setMethod == null) colattr.IsIgnore = true;
 | 
									if (setMethod == null) colattr.IsIgnore = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,7 +122,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			trytb.VersionColumn = trytb.Columns.Values.Where(a => a.Attribute.IsVersion == true).LastOrDefault();
 | 
								trytb.VersionColumn = trytb.Columns.Values.Where(a => a.Attribute.IsVersion == true).LastOrDefault();
 | 
				
			||||||
			if (trytb.VersionColumn != null) {
 | 
								if (trytb.VersionColumn != null) {
 | 
				
			||||||
				if (trytb.VersionColumn.CsType.IsNullableType() || trytb.VersionColumn.CsType.IsNumberType() == false)
 | 
									if (trytb.VersionColumn.Attribute.MapType.IsNullableType() || trytb.VersionColumn.Attribute.MapType.IsNumberType() == false)
 | 
				
			||||||
					throw new Exception($"属性{trytb.VersionColumn.CsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型,并且不可为 Nullable");
 | 
										throw new Exception($"属性{trytb.VersionColumn.CsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型,并且不可为 Nullable");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
 | 
								trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
 | 
				
			||||||
@@ -145,14 +153,14 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						var finddbtbs = common.dbTables.Where(a => string.Compare(a.Name, trytb.CsName, true) == 0 || string.Compare(a.Name, trytb.DbName, true) == 0);
 | 
											var finddbtbs = common.dbTables.Where(a => string.Compare(a.Name, trytb.CsName, true) == 0 || string.Compare(a.Name, trytb.DbName, true) == 0);
 | 
				
			||||||
						foreach (var dbtb in finddbtbs) {
 | 
											foreach (var dbtb in finddbtbs) {
 | 
				
			||||||
							foreach (var dbident in dbtb.Identitys) {
 | 
												foreach (var dbident in dbtb.Identitys) {
 | 
				
			||||||
								if (trytb.Columns.TryGetValue(dbident.Name, out var trycol) && trycol.CsType == dbident.CsType ||
 | 
													if (trytb.Columns.TryGetValue(dbident.Name, out var trycol) && trycol.Attribute.MapType == dbident.CsType ||
 | 
				
			||||||
									trytb.ColumnsByCs.TryGetValue(dbident.Name, out trycol) && trycol.CsType == dbident.CsType) {
 | 
														trytb.ColumnsByCs.TryGetValue(dbident.Name, out trycol) && trycol.Attribute.MapType == dbident.CsType) {
 | 
				
			||||||
									trycol.Attribute.IsIdentity = true;
 | 
														trycol.Attribute.IsIdentity = true;
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							foreach (var dbpk in dbtb.Primarys) {
 | 
												foreach (var dbpk in dbtb.Primarys) {
 | 
				
			||||||
								if (trytb.Columns.TryGetValue(dbpk.Name, out var trycol) && trycol.CsType == dbpk.CsType ||
 | 
													if (trytb.Columns.TryGetValue(dbpk.Name, out var trycol) && trycol.Attribute.MapType == dbpk.CsType ||
 | 
				
			||||||
									trytb.ColumnsByCs.TryGetValue(dbpk.Name, out trycol) && trycol.CsType == dbpk.CsType) {
 | 
														trytb.ColumnsByCs.TryGetValue(dbpk.Name, out trycol) && trycol.Attribute.MapType == dbpk.CsType) {
 | 
				
			||||||
									trycol.Attribute.IsPrimary = true;
 | 
														trycol.Attribute.IsPrimary = true;
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
@@ -682,8 +690,8 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			public static PropertyInfo PropertyDataIndex = typeof(RowInfo).GetProperty("DataIndex");
 | 
								public static PropertyInfo PropertyDataIndex = typeof(RowInfo).GetProperty("DataIndex");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal static MethodInfo MethodDataReaderGetValue = typeof(DbDataReader).GetMethod("GetValue");
 | 
							internal static MethodInfo MethodDataReaderGetValue = typeof(DbDataReader).GetMethod("GetValue");
 | 
				
			||||||
		internal static RowInfo ExecuteArrayRowReadClassOrTuple(Type type, int[] indexes, DbDataReader row, int dataIndex, CommonUtils _commonUtils) {
 | 
							internal static RowInfo ExecuteArrayRowReadClassOrTuple(Type typeOrg, int[] indexes, DbDataReader row, int dataIndex, CommonUtils _commonUtils) {
 | 
				
			||||||
			var func = _dicExecuteArrayRowReadClassOrTuple.GetOrAdd(type, s => {
 | 
								var func = _dicExecuteArrayRowReadClassOrTuple.GetOrAdd(typeOrg, type => {
 | 
				
			||||||
				var returnTarget = Expression.Label(typeof(RowInfo));
 | 
									var returnTarget = Expression.Label(typeof(RowInfo));
 | 
				
			||||||
				var typeExp = Expression.Parameter(typeof(Type), "type");
 | 
									var typeExp = Expression.Parameter(typeof(Type), "type");
 | 
				
			||||||
				var indexesExp = Expression.Parameter(typeof(int[]), "indexes");
 | 
									var indexesExp = Expression.Parameter(typeof(int[]), "indexes");
 | 
				
			||||||
@@ -813,24 +821,25 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
					});
 | 
										});
 | 
				
			||||||
					foreach (var ctorParm in ctorParms) {
 | 
										foreach (var ctorParm in ctorParms) {
 | 
				
			||||||
						if (typetb.ColumnsByCsIgnore.ContainsKey(ctorParm.Name)) continue;
 | 
											if (typetb.ColumnsByCsIgnore.ContainsKey(ctorParm.Name)) continue;
 | 
				
			||||||
 | 
											var readType = typetb.ColumnsByCs.TryGetValue(ctorParm.Name, out var trycol) ? trycol.Attribute.MapType : ctorParm.ParameterType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						var ispkExp = new List<Expression>();
 | 
											var ispkExp = new List<Expression>();
 | 
				
			||||||
						Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp));
 | 
											Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp));
 | 
				
			||||||
						Expression readExpAssign = null; //加速缓存
 | 
											Expression readExpAssign = null; //加速缓存
 | 
				
			||||||
						if (ctorParm.ParameterType.IsArray) readExpAssign = Expression.New(RowInfo.Constructor,
 | 
											if (readType.IsArray) readExpAssign = Expression.New(RowInfo.Constructor,
 | 
				
			||||||
							GetDataReaderValueBlockExpression(ctorParm.ParameterType, readpkvalExp),
 | 
												GetDataReaderValueBlockExpression(readType, readpkvalExp),
 | 
				
			||||||
							//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(ctorParm.ParameterType), readpkvalExp }),
 | 
												//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(readType), readpkvalExp }),
 | 
				
			||||||
							Expression.Add(dataIndexExp, Expression.Constant(1))
 | 
												Expression.Add(dataIndexExp, Expression.Constant(1))
 | 
				
			||||||
						);
 | 
											);
 | 
				
			||||||
						else {
 | 
											else {
 | 
				
			||||||
							var proptypeGeneric = ctorParm.ParameterType;
 | 
												var proptypeGeneric = readType;
 | 
				
			||||||
							if (proptypeGeneric.IsNullableType()) proptypeGeneric = proptypeGeneric.GenericTypeArguments.First();
 | 
												if (proptypeGeneric.IsNullableType()) proptypeGeneric = proptypeGeneric.GenericTypeArguments.First();
 | 
				
			||||||
							if (proptypeGeneric.IsEnum ||
 | 
												if (proptypeGeneric.IsEnum ||
 | 
				
			||||||
								dicExecuteArrayRowReadClassOrTuple.ContainsKey(proptypeGeneric)) {
 | 
													dicExecuteArrayRowReadClassOrTuple.ContainsKey(proptypeGeneric)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								//判断主键为空,则整个对象不读取
 | 
													//判断主键为空,则整个对象不读取
 | 
				
			||||||
								//blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)));
 | 
													//blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)));
 | 
				
			||||||
								if (typetb.ColumnsByCs.TryGetValue(ctorParm.Name, out var trycol) && trycol.Attribute.IsPrimary == true) {
 | 
													if (trycol?.Attribute.IsPrimary == true) {
 | 
				
			||||||
									ispkExp.Add(
 | 
														ispkExp.Add(
 | 
				
			||||||
										Expression.IfThen(
 | 
															Expression.IfThen(
 | 
				
			||||||
											Expression.AndAlso(
 | 
																Expression.AndAlso(
 | 
				
			||||||
@@ -846,19 +855,22 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
								}
 | 
													}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								readExpAssign = Expression.New(RowInfo.Constructor,
 | 
													readExpAssign = Expression.New(RowInfo.Constructor,
 | 
				
			||||||
									GetDataReaderValueBlockExpression(ctorParm.ParameterType, readpkvalExp),
 | 
														GetDataReaderValueBlockExpression(readType, readpkvalExp),
 | 
				
			||||||
									//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(ctorParm.ParameterType), readpkvalExp }),
 | 
														//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(readType), readpkvalExp }),
 | 
				
			||||||
									Expression.Add(dataIndexExp, Expression.Constant(1))
 | 
														Expression.Add(dataIndexExp, Expression.Constant(1))
 | 
				
			||||||
								);
 | 
													);
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								readExpAssign = Expression.New(RowInfo.Constructor,
 | 
													readExpAssign = Expression.New(RowInfo.Constructor,
 | 
				
			||||||
									Expression.MakeMemberAccess(Expression.Call(MethodExecuteArrayRowReadClassOrTuple, new Expression[] { Expression.Constant(ctorParm.ParameterType), indexesExp, rowExp, dataIndexExp, commonUtilExp }), RowInfo.PropertyValue),
 | 
														Expression.MakeMemberAccess(Expression.Call(MethodExecuteArrayRowReadClassOrTuple, new Expression[] { Expression.Constant(readType), indexesExp, rowExp, dataIndexExp, commonUtilExp }), RowInfo.PropertyValue),
 | 
				
			||||||
									Expression.Add(dataIndexExp, Expression.Constant(1)));
 | 
														Expression.Add(dataIndexExp, Expression.Constant(1)));
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						var varctorParm = Expression.Variable(ctorParm.ParameterType, $"ctorParm{ctorParm.Name}");
 | 
											var varctorParm = Expression.Variable(ctorParm.ParameterType, $"ctorParm{ctorParm.Name}");
 | 
				
			||||||
						readExpValueParms.Add(varctorParm);
 | 
											readExpValueParms.Add(varctorParm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (trycol != null && trycol.Attribute.MapType != ctorParm.ParameterType)
 | 
				
			||||||
 | 
												ispkExp.Add(Expression.Assign(readExpValue, GetDataReaderValueBlockExpression(ctorParm.ParameterType, readExpValue)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						ispkExp.Add(
 | 
											ispkExp.Add(
 | 
				
			||||||
							Expression.IfThen(
 | 
												Expression.IfThen(
 | 
				
			||||||
								Expression.IsFalse(readpknullExp),
 | 
													Expression.IsFalse(readpknullExp),
 | 
				
			||||||
@@ -869,6 +881,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
								)
 | 
													)
 | 
				
			||||||
							)
 | 
												)
 | 
				
			||||||
						);
 | 
											);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						blockExp.AddRange(new Expression[] {
 | 
											blockExp.AddRange(new Expression[] {
 | 
				
			||||||
							Expression.Assign(tryidxExp, dataIndexExp),
 | 
												Expression.Assign(tryidxExp, dataIndexExp),
 | 
				
			||||||
							readVal,
 | 
												readVal,
 | 
				
			||||||
@@ -900,25 +913,26 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
					var propIndex = 0;
 | 
										var propIndex = 0;
 | 
				
			||||||
					foreach (var prop in props) {
 | 
										foreach (var prop in props) {
 | 
				
			||||||
						if (typetb.ColumnsByCsIgnore.ContainsKey(prop.Name)) continue;
 | 
											if (typetb.ColumnsByCsIgnore.ContainsKey(prop.Name)) continue;
 | 
				
			||||||
 | 
											var readType = typetb.ColumnsByCs.TryGetValue(prop.Name, out var trycol) ? trycol.Attribute.MapType : prop.PropertyType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						var ispkExp = new List<Expression>();
 | 
											var ispkExp = new List<Expression>();
 | 
				
			||||||
						var propGetSetMethod = prop.GetSetMethod();
 | 
											var propGetSetMethod = prop.GetSetMethod();
 | 
				
			||||||
						Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, tryidxExp));
 | 
											Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, tryidxExp));
 | 
				
			||||||
						Expression readExpAssign = null; //加速缓存
 | 
											Expression readExpAssign = null; //加速缓存
 | 
				
			||||||
						if (prop.PropertyType.IsArray) readExpAssign = Expression.New(RowInfo.Constructor,
 | 
											if (readType.IsArray) readExpAssign = Expression.New(RowInfo.Constructor,
 | 
				
			||||||
							GetDataReaderValueBlockExpression(prop.PropertyType, readpkvalExp),
 | 
												GetDataReaderValueBlockExpression(readType, readpkvalExp),
 | 
				
			||||||
							//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(prop.PropertyType), readpkvalExp }),
 | 
												//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(readType), readpkvalExp }),
 | 
				
			||||||
							Expression.Add(tryidxExp, Expression.Constant(1))
 | 
												Expression.Add(tryidxExp, Expression.Constant(1))
 | 
				
			||||||
						);
 | 
											);
 | 
				
			||||||
						else {
 | 
											else {
 | 
				
			||||||
							var proptypeGeneric = prop.PropertyType;
 | 
												var proptypeGeneric = readType;
 | 
				
			||||||
							if (proptypeGeneric.IsNullableType()) proptypeGeneric = proptypeGeneric.GenericTypeArguments.First();
 | 
												if (proptypeGeneric.IsNullableType()) proptypeGeneric = proptypeGeneric.GenericTypeArguments.First();
 | 
				
			||||||
							if (proptypeGeneric.IsEnum ||
 | 
												if (proptypeGeneric.IsEnum ||
 | 
				
			||||||
								dicExecuteArrayRowReadClassOrTuple.ContainsKey(proptypeGeneric)) {
 | 
													dicExecuteArrayRowReadClassOrTuple.ContainsKey(proptypeGeneric)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								//判断主键为空,则整个对象不读取
 | 
													//判断主键为空,则整个对象不读取
 | 
				
			||||||
								//blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)));
 | 
													//blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)));
 | 
				
			||||||
								if (typetb.ColumnsByCs.TryGetValue(prop.Name, out var trycol) && trycol.Attribute.IsPrimary == true) {
 | 
													if (trycol?.Attribute.IsPrimary == true) {
 | 
				
			||||||
									ispkExp.Add(
 | 
														ispkExp.Add(
 | 
				
			||||||
										Expression.IfThen(
 | 
															Expression.IfThen(
 | 
				
			||||||
											Expression.AndAlso(
 | 
																Expression.AndAlso(
 | 
				
			||||||
@@ -937,17 +951,20 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
								}
 | 
													}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								readExpAssign = Expression.New(RowInfo.Constructor,
 | 
													readExpAssign = Expression.New(RowInfo.Constructor,
 | 
				
			||||||
									GetDataReaderValueBlockExpression(prop.PropertyType, readpkvalExp),
 | 
														GetDataReaderValueBlockExpression(readType, readpkvalExp),
 | 
				
			||||||
									//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(prop.PropertyType), readpkvalExp }),
 | 
														//Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(readType), readpkvalExp }),
 | 
				
			||||||
									Expression.Add(tryidxExp, Expression.Constant(1))
 | 
														Expression.Add(tryidxExp, Expression.Constant(1))
 | 
				
			||||||
								);
 | 
													);
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								++propIndex;
 | 
													++propIndex;
 | 
				
			||||||
								continue;
 | 
													continue;
 | 
				
			||||||
								//readExpAssign = Expression.Call(MethodExecuteArrayRowReadClassOrTuple, new Expression[] { Expression.Constant(prop.PropertyType), indexesExp, rowExp, tryidxExp });
 | 
													//readExpAssign = Expression.Call(MethodExecuteArrayRowReadClassOrTuple, new Expression[] { Expression.Constant(readType), indexesExp, rowExp, tryidxExp });
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (trycol != null && trycol.Attribute.MapType != prop.PropertyType)
 | 
				
			||||||
 | 
												ispkExp.Add(Expression.Assign(readExpValue, GetDataReaderValueBlockExpression(prop.PropertyType, readExpValue)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						ispkExp.Add(
 | 
											ispkExp.Add(
 | 
				
			||||||
							Expression.IfThen(
 | 
												Expression.IfThen(
 | 
				
			||||||
								Expression.IsFalse(readpknullExp),
 | 
													Expression.IsFalse(readpknullExp),
 | 
				
			||||||
@@ -986,7 +1003,7 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
				return Expression.Lambda<Func<Type, int[], DbDataReader, int, CommonUtils, RowInfo>>(
 | 
									return Expression.Lambda<Func<Type, int[], DbDataReader, int, CommonUtils, RowInfo>>(
 | 
				
			||||||
					Expression.Block(new[] { retExp, readExp, tryidxExp, readpknullExp, readpkvalExp, readExpsIndex, indexesLengthExp }.Concat(readExpValueParms), blockExp), new[] { typeExp, indexesExp, rowExp, dataIndexExp, commonUtilExp }).Compile();
 | 
										Expression.Block(new[] { retExp, readExp, tryidxExp, readpknullExp, readpkvalExp, readExpsIndex, indexesLengthExp }.Concat(readExpValueParms), blockExp), new[] { typeExp, indexesExp, rowExp, dataIndexExp, commonUtilExp }).Compile();
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
			return func(type, indexes, row, dataIndex, _commonUtils);
 | 
								return func(typeOrg, indexes, row, dataIndex, _commonUtils);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal static MethodInfo MethodExecuteArrayRowReadClassOrTuple = typeof(Utils).GetMethod("ExecuteArrayRowReadClassOrTuple", BindingFlags.Static | BindingFlags.NonPublic);
 | 
							internal static MethodInfo MethodExecuteArrayRowReadClassOrTuple = typeof(Utils).GetMethod("ExecuteArrayRowReadClassOrTuple", BindingFlags.Static | BindingFlags.NonPublic);
 | 
				
			||||||
@@ -1012,16 +1029,24 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
			act(info, value);
 | 
								act(info, value);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static BigInteger ToBigInteger(string that) {
 | 
				
			||||||
 | 
								if (string.IsNullOrEmpty(that)) return 0;
 | 
				
			||||||
 | 
								if (BigInteger.TryParse(that, System.Globalization.NumberStyles.Any, null, out var trybigint)) return trybigint;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							static string ToStringConcat(object obj) {
 | 
				
			||||||
 | 
								if (obj == null) return null;
 | 
				
			||||||
 | 
								return string.Concat(obj);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static ConcurrentDictionary<Type, ConcurrentDictionary<Type, Func<object, object>>> _dicGetDataReaderValue = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, Func<object, object>>>();
 | 
							static ConcurrentDictionary<Type, ConcurrentDictionary<Type, Func<object, object>>> _dicGetDataReaderValue = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, Func<object, object>>>();
 | 
				
			||||||
		static MethodInfo MethodArrayGetValue = typeof(Array).GetMethod("GetValue", new[] { typeof(int) });
 | 
							static MethodInfo MethodArrayGetValue = typeof(Array).GetMethod("GetValue", new[] { typeof(int) });
 | 
				
			||||||
		static MethodInfo MethodArrayGetLength = typeof(Array).GetMethod("GetLength", new[] { typeof(int) });
 | 
							static MethodInfo MethodArrayGetLength = typeof(Array).GetMethod("GetLength", new[] { typeof(int) });
 | 
				
			||||||
		static MethodInfo MethodMygisGeometryParse = typeof(MygisGeometry).GetMethod("Parse", new[] { typeof(string) });
 | 
							static MethodInfo MethodMygisGeometryParse = typeof(MygisGeometry).GetMethod("Parse", new[] { typeof(string) });
 | 
				
			||||||
		static MethodInfo MethodGuidTryParse = typeof(Guid).GetMethod("TryParse", new[] { typeof(string), typeof(Guid).MakeByRefType() });
 | 
							static MethodInfo MethodGuidTryParse = typeof(Guid).GetMethod("TryParse", new[] { typeof(string), typeof(Guid).MakeByRefType() });
 | 
				
			||||||
		static MethodInfo MethodEnumParse = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) });
 | 
							static MethodInfo MethodEnumParse = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) });
 | 
				
			||||||
		static MethodInfo MethodToString = typeof(string).GetMethod("Concat", new[] { typeof(object) });
 | 
					 | 
				
			||||||
		static MethodInfo MethodConvertChangeType = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) });
 | 
							static MethodInfo MethodConvertChangeType = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) });
 | 
				
			||||||
		static MethodInfo MethodTimeSpanFromSeconds = typeof(TimeSpan).GetMethod("FromSeconds");
 | 
							static MethodInfo MethodTimeSpanFromSeconds = typeof(TimeSpan).GetMethod("FromSeconds");
 | 
				
			||||||
		static MethodInfo MethodDoubleParse = typeof(double).GetMethod("Parse", new[] { typeof(string) });
 | 
					 | 
				
			||||||
		static MethodInfo MethodJTokenParse = typeof(JToken).GetMethod("Parse", new[] { typeof(string) });
 | 
							static MethodInfo MethodJTokenParse = typeof(JToken).GetMethod("Parse", new[] { typeof(string) });
 | 
				
			||||||
		static MethodInfo MethodJObjectParse = typeof(JObject).GetMethod("Parse", new[] { typeof(string) });
 | 
							static MethodInfo MethodJObjectParse = typeof(JObject).GetMethod("Parse", new[] { typeof(string) });
 | 
				
			||||||
		static MethodInfo MethodJArrayParse = typeof(JArray).GetMethod("Parse", new[] { typeof(string) });
 | 
							static MethodInfo MethodJArrayParse = typeof(JArray).GetMethod("Parse", new[] { typeof(string) });
 | 
				
			||||||
@@ -1036,8 +1061,11 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
		static MethodInfo MethodDoubleTryParse = typeof(double).GetMethod("TryParse", new[] { typeof(string), typeof(double).MakeByRefType() });
 | 
							static MethodInfo MethodDoubleTryParse = typeof(double).GetMethod("TryParse", new[] { typeof(string), typeof(double).MakeByRefType() });
 | 
				
			||||||
		static MethodInfo MethodFloatTryParse = typeof(float).GetMethod("TryParse", new[] { typeof(string), typeof(float).MakeByRefType() });
 | 
							static MethodInfo MethodFloatTryParse = typeof(float).GetMethod("TryParse", new[] { typeof(string), typeof(float).MakeByRefType() });
 | 
				
			||||||
		static MethodInfo MethodDecimalTryParse = typeof(decimal).GetMethod("TryParse", new[] { typeof(string), typeof(decimal).MakeByRefType() });
 | 
							static MethodInfo MethodDecimalTryParse = typeof(decimal).GetMethod("TryParse", new[] { typeof(string), typeof(decimal).MakeByRefType() });
 | 
				
			||||||
 | 
							static MethodInfo MethodTimeSpanTryParse = typeof(TimeSpan).GetMethod("TryParse", new[] { typeof(string), typeof(TimeSpan).MakeByRefType() });
 | 
				
			||||||
		static MethodInfo MethodDateTimeTryParse = typeof(DateTime).GetMethod("TryParse", new[] { typeof(string), typeof(DateTime).MakeByRefType() });
 | 
							static MethodInfo MethodDateTimeTryParse = typeof(DateTime).GetMethod("TryParse", new[] { typeof(string), typeof(DateTime).MakeByRefType() });
 | 
				
			||||||
		static MethodInfo MethodDateTimeOffsetTryParse = typeof(DateTimeOffset).GetMethod("TryParse", new[] { typeof(string), typeof(DateTimeOffset).MakeByRefType() });
 | 
							static MethodInfo MethodDateTimeOffsetTryParse = typeof(DateTimeOffset).GetMethod("TryParse", new[] { typeof(string), typeof(DateTimeOffset).MakeByRefType() });
 | 
				
			||||||
 | 
							static MethodInfo MethodToString = typeof(Utils).GetMethod("ToStringConcat", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(object) }, null);
 | 
				
			||||||
 | 
							static MethodInfo MethodBigIntegerParse = typeof(Utils).GetMethod("ToBigInteger", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(string) }, null);
 | 
				
			||||||
		public static Expression GetDataReaderValueBlockExpression(Type type, Expression value) {
 | 
							public static Expression GetDataReaderValueBlockExpression(Type type, Expression value) {
 | 
				
			||||||
			var returnTarget = Expression.Label(typeof(object));
 | 
								var returnTarget = Expression.Label(typeof(object));
 | 
				
			||||||
			var valueExp = Expression.Variable(typeof(object), "locvalue");
 | 
								var valueExp = Expression.Variable(typeof(object), "locvalue");
 | 
				
			||||||
@@ -1088,11 +1116,6 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
				ParameterExpression tryparseVarExp = null;
 | 
									ParameterExpression tryparseVarExp = null;
 | 
				
			||||||
				switch (type.FullName) {
 | 
									switch (type.FullName) {
 | 
				
			||||||
					case "System.Guid":
 | 
										case "System.Guid":
 | 
				
			||||||
						//return Expression.IfThenElse(
 | 
					 | 
				
			||||||
						//	Expression.TypeEqual(valueExp, type),
 | 
					 | 
				
			||||||
						//	Expression.Return(returnTarget, valueExp),
 | 
					 | 
				
			||||||
						//	Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodGuidParse, Expression.Convert(valueExp, typeof(string))), typeof(object)))
 | 
					 | 
				
			||||||
						//);
 | 
					 | 
				
			||||||
						tryparseExp = Expression.Block(
 | 
											tryparseExp = Expression.Block(
 | 
				
			||||||
						   new[] { tryparseVarExp = Expression.Variable(typeof(Guid)) },
 | 
											   new[] { tryparseVarExp = Expression.Variable(typeof(Guid)) },
 | 
				
			||||||
						   new Expression[] {
 | 
											   new Expression[] {
 | 
				
			||||||
@@ -1114,11 +1137,23 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
					case "Newtonsoft.Json.Linq.JObject": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJObjectParse, Expression.Convert(valueExp, typeof(string))), typeof(JObject)));
 | 
										case "Newtonsoft.Json.Linq.JObject": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJObjectParse, Expression.Convert(valueExp, typeof(string))), typeof(JObject)));
 | 
				
			||||||
					case "Newtonsoft.Json.Linq.JArray": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJArrayParse, Expression.Convert(valueExp, typeof(string))), typeof(JArray)));
 | 
										case "Newtonsoft.Json.Linq.JArray": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJArrayParse, Expression.Convert(valueExp, typeof(string))), typeof(JArray)));
 | 
				
			||||||
					case "Npgsql.LegacyPostgis.PostgisGeometry": return Expression.Return(returnTarget, valueExp);
 | 
										case "Npgsql.LegacyPostgis.PostgisGeometry": return Expression.Return(returnTarget, valueExp);
 | 
				
			||||||
 | 
										case "System.Numerics.BigInteger": return Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodBigIntegerParse, Expression.Call(MethodToString, valueExp)), typeof(object)));
 | 
				
			||||||
					case "System.TimeSpan":
 | 
										case "System.TimeSpan":
 | 
				
			||||||
						return Expression.IfThenElse(
 | 
											ParameterExpression tryparseVarTsExp, valueStrExp;
 | 
				
			||||||
							Expression.TypeEqual(valueExp, type),
 | 
											return Expression.Block(
 | 
				
			||||||
							Expression.Return(returnTarget, valueExp),
 | 
												   new[] { tryparseVarExp = Expression.Variable(typeof(double)), tryparseVarTsExp = Expression.Variable(typeof(TimeSpan)), valueStrExp = Expression.Variable(typeof(string)) },
 | 
				
			||||||
							Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeSpanFromSeconds, Expression.Call(MethodDoubleParse, Expression.Call(MethodToString, valueExp))), typeof(object)))
 | 
												   new Expression[] {
 | 
				
			||||||
 | 
														Expression.Assign(valueStrExp, Expression.Call(MethodToString, valueExp)),
 | 
				
			||||||
 | 
														Expression.IfThenElse(
 | 
				
			||||||
 | 
															Expression.IsTrue(Expression.Call(MethodDoubleTryParse, valueStrExp, tryparseVarExp)),
 | 
				
			||||||
 | 
															Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodTimeSpanFromSeconds, tryparseVarExp), typeof(object))),
 | 
				
			||||||
 | 
															Expression.IfThenElse(
 | 
				
			||||||
 | 
																Expression.IsTrue(Expression.Call(MethodTimeSpanTryParse, valueStrExp, tryparseVarTsExp)),
 | 
				
			||||||
 | 
																Expression.Return(returnTarget, Expression.Convert(tryparseVarTsExp, typeof(object))),
 | 
				
			||||||
 | 
																Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object)))
 | 
				
			||||||
 | 
															)
 | 
				
			||||||
 | 
														)
 | 
				
			||||||
 | 
												   }
 | 
				
			||||||
						   );
 | 
											   );
 | 
				
			||||||
					case "System.SByte":
 | 
										case "System.SByte":
 | 
				
			||||||
						tryparseExp = Expression.Block(
 | 
											tryparseExp = Expression.Block(
 | 
				
			||||||
@@ -1308,16 +1343,22 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
						Expression.SwitchCase(tryparseBooleanExp, Expression.Constant(typeof(bool))),
 | 
											Expression.SwitchCase(tryparseBooleanExp, Expression.Constant(typeof(bool))),
 | 
				
			||||||
						Expression.SwitchCase(Expression.Return(returnTarget, Expression.Call(MethodConvertChangeType, valueExp, Expression.Constant(type, typeof(Type)))), Expression.Constant(type))
 | 
											Expression.SwitchCase(Expression.Return(returnTarget, Expression.Call(MethodConvertChangeType, valueExp, Expression.Constant(type, typeof(Type)))), Expression.Constant(type))
 | 
				
			||||||
					);
 | 
										);
 | 
				
			||||||
 | 
									else if (type == typeof(string))
 | 
				
			||||||
 | 
										switchExp = Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodToString, valueExp), typeof(object)));
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					switchExp = Expression.Return(returnTarget, Expression.Call(MethodConvertChangeType, valueExp, Expression.Constant(type, typeof(Type))));
 | 
										switchExp = Expression.Return(returnTarget, Expression.Call(MethodConvertChangeType, valueExp, Expression.Constant(type, typeof(Type))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									var defaultRetExp = type == typeof(string) ?
 | 
				
			||||||
 | 
										Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodToString, valueExp), typeof(object))) :
 | 
				
			||||||
 | 
										Expression.Return(returnTarget, Expression.Call(MethodConvertChangeType, valueExp, Expression.Constant(type, typeof(Type))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				return Expression.IfThenElse(
 | 
									return Expression.IfThenElse(
 | 
				
			||||||
					Expression.TypeEqual(valueExp, type),
 | 
										Expression.TypeEqual(valueExp, type),
 | 
				
			||||||
					Expression.Return(returnTarget, valueExp),
 | 
										Expression.Return(returnTarget, valueExp),
 | 
				
			||||||
					Expression.IfThenElse(
 | 
										Expression.IfThenElse(
 | 
				
			||||||
						Expression.TypeEqual(valueExp, typeof(string)),
 | 
											Expression.TypeEqual(valueExp, typeof(string)),
 | 
				
			||||||
						switchExp,
 | 
											switchExp,
 | 
				
			||||||
						Expression.Return(returnTarget, Expression.Call(MethodConvertChangeType, valueExp, Expression.Constant(type, typeof(Type))))
 | 
											defaultRetExp
 | 
				
			||||||
					)
 | 
										)
 | 
				
			||||||
				);
 | 
									);
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
@@ -1345,132 +1386,6 @@ namespace FreeSql.Internal {
 | 
				
			|||||||
				return Expression.Lambda<Func<object, object>>(exp, parmExp).Compile();
 | 
									return Expression.Lambda<Func<object, object>>(exp, parmExp).Compile();
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
			return func(value);
 | 
								return func(value);
 | 
				
			||||||
			#region oldcode
 | 
					 | 
				
			||||||
			//var func = _dicGetDataReaderValue.GetOrAdd(type, k1 => new ConcurrentDictionary<Type, Func<object, object>>()).GetOrAdd(value.GetType(), valueType => {
 | 
					 | 
				
			||||||
			//	var returnTarget = Expression.Label(typeof(object));
 | 
					 | 
				
			||||||
			//	var parmExp = Expression.Parameter(typeof(object), "value");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	if (type.FullName == "System.Byte[]") return Expression.Lambda<Func<object, object>>(parmExp, parmExp).Compile();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	if (type.IsArray) {
 | 
					 | 
				
			||||||
			//		var elementType = type.GetElementType();
 | 
					 | 
				
			||||||
			//		if (elementType == valueType.GetElementType()) return Expression.Lambda<Func<object, object>>(parmExp, parmExp).Compile();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//		var ret = Expression.Variable(type, "ret");
 | 
					 | 
				
			||||||
			//		var arr = Expression.Variable(valueType, "arr");
 | 
					 | 
				
			||||||
			//		var arrlen = Expression.Variable(typeof(int), "arrlen");
 | 
					 | 
				
			||||||
			//		var x = Expression.Variable(typeof(int), "x");
 | 
					 | 
				
			||||||
			//		var readval = Expression.Variable(typeof(object), "readval");
 | 
					 | 
				
			||||||
			//		var label = Expression.Label(typeof(int));
 | 
					 | 
				
			||||||
			//		return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//			Expression.Block(
 | 
					 | 
				
			||||||
			//				new[] { ret, arr, arrlen, readval, x },
 | 
					 | 
				
			||||||
			//				Expression.Assign(arr, Expression.TypeAs(parmExp, valueType)),
 | 
					 | 
				
			||||||
			//				Expression.Assign(arrlen, Expression.ArrayLength(arr)),
 | 
					 | 
				
			||||||
			//				Expression.Assign(x, Expression.Constant(0)),
 | 
					 | 
				
			||||||
			//				Expression.Assign(ret, Expression.NewArrayBounds(elementType, arrlen)),
 | 
					 | 
				
			||||||
			//				Expression.Loop(
 | 
					 | 
				
			||||||
			//					Expression.IfThenElse(
 | 
					 | 
				
			||||||
			//						Expression.LessThan(x, arrlen),
 | 
					 | 
				
			||||||
			//						Expression.Block(
 | 
					 | 
				
			||||||
			//							Expression.Assign(readval, Expression.Call(
 | 
					 | 
				
			||||||
			//								MethodGetDataReaderValue,
 | 
					 | 
				
			||||||
			//								Expression.Constant(elementType, typeof(Type)),
 | 
					 | 
				
			||||||
			//								Expression.Convert(Expression.ArrayAccess(arr, x), typeof(object))
 | 
					 | 
				
			||||||
			//							)),
 | 
					 | 
				
			||||||
			//							Expression.IfThenElse(
 | 
					 | 
				
			||||||
			//								Expression.Equal(readval, Expression.Constant(null)),
 | 
					 | 
				
			||||||
			//								Expression.Assign(Expression.ArrayAccess(ret, x), Expression.Default(elementType)),
 | 
					 | 
				
			||||||
			//								Expression.Assign(Expression.ArrayAccess(ret, x), Expression.Convert(readval, elementType))
 | 
					 | 
				
			||||||
			//							),
 | 
					 | 
				
			||||||
			//							Expression.PostIncrementAssign(x)
 | 
					 | 
				
			||||||
			//						),
 | 
					 | 
				
			||||||
			//						Expression.Break(label, x)
 | 
					 | 
				
			||||||
			//					),
 | 
					 | 
				
			||||||
			//					label
 | 
					 | 
				
			||||||
			//				),
 | 
					 | 
				
			||||||
			//				Expression.Return(returnTarget, ret),
 | 
					 | 
				
			||||||
			//				Expression.Label(returnTarget, Expression.Default(typeof(object)))
 | 
					 | 
				
			||||||
			//			), parmExp).Compile();
 | 
					 | 
				
			||||||
			//	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	if (type.IsNullableType()) type = type.GenericTypeArguments.First();
 | 
					 | 
				
			||||||
			//	if (type.IsEnum) return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//		Expression.Call(
 | 
					 | 
				
			||||||
			//			MethodEnumParse,
 | 
					 | 
				
			||||||
			//			Expression.Constant(type, typeof(Type)),
 | 
					 | 
				
			||||||
			//			Expression.Call(MethodToString, parmExp),
 | 
					 | 
				
			||||||
			//			Expression.Constant(true, typeof(bool))
 | 
					 | 
				
			||||||
			//		) , parmExp).Compile();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//	switch (type.FullName) {
 | 
					 | 
				
			||||||
			//		case "System.Guid":
 | 
					 | 
				
			||||||
			//			if (valueType != type) return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.Convert(Expression.Call(MethodGuidParse, Expression.Convert(parmExp, typeof(string))), typeof(object))
 | 
					 | 
				
			||||||
			//				, parmExp).Compile();
 | 
					 | 
				
			||||||
			//			return Expression.Lambda<Func<object, object>>(parmExp, parmExp).Compile();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			//		case "MygisPoint": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(MethodMygisGeometryParse, Expression.Convert(parmExp, typeof(string))),
 | 
					 | 
				
			||||||
			//					typeof(MygisPoint)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "MygisLineString": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(MethodMygisGeometryParse, Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(MygisLineString)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "MygisPolygon": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(MethodMygisGeometryParse, Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(MygisPolygon)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "MygisMultiPoint": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(MethodMygisGeometryParse, Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(MygisMultiPoint)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "MygisMultiLineString": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(MethodMygisGeometryParse, Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(MygisMultiLineString)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "MygisMultiPolygon": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(MethodMygisGeometryParse, Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(MygisMultiPolygon)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "Newtonsoft.Json.Linq.JToken": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(typeof(JToken).GetMethod("Parse", new[] { typeof(string) }), Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(JToken)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "Newtonsoft.Json.Linq.JObject": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(typeof(JObject).GetMethod("Parse", new[] { typeof(string) }), Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(JObject)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "Newtonsoft.Json.Linq.JArray": return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//				Expression.TypeAs(
 | 
					 | 
				
			||||||
			//					Expression.Call(typeof(JArray).GetMethod("Parse", new[] { typeof(string) }), Expression.Convert(parmExp, typeof(string))), 
 | 
					 | 
				
			||||||
			//					typeof(JArray)
 | 
					 | 
				
			||||||
			//				), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		case "Npgsql.LegacyPostgis.PostgisGeometry": return Expression.Lambda<Func<object, object>>(parmExp, parmExp).Compile();
 | 
					 | 
				
			||||||
			//	}
 | 
					 | 
				
			||||||
			//	if (type != valueType) {
 | 
					 | 
				
			||||||
			//		if (type.FullName == "System.TimeSpan") return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//			Expression.Convert(Expression.Call(
 | 
					 | 
				
			||||||
			//				MethodTimeSpanFromSeconds,
 | 
					 | 
				
			||||||
			//				Expression.Call(MethodDoubleParse, Expression.Call(MethodToString, parmExp))
 | 
					 | 
				
			||||||
			//			), typeof(object)), parmExp).Compile();
 | 
					 | 
				
			||||||
			//		return Expression.Lambda<Func<object, object>>(
 | 
					 | 
				
			||||||
			//			Expression.Call(MethodConvertChangeType, parmExp, Expression.Constant(type, typeof(Type)))
 | 
					 | 
				
			||||||
			//		, parmExp).Compile();
 | 
					 | 
				
			||||||
			//	}
 | 
					 | 
				
			||||||
			//	return Expression.Lambda<Func<object, object>>(parmExp, parmExp).Compile();
 | 
					 | 
				
			||||||
			//});
 | 
					 | 
				
			||||||
			//return func(value);
 | 
					 | 
				
			||||||
			#endregion
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal static object GetDataReaderValue22(Type type, object value) {
 | 
							internal static object GetDataReaderValue22(Type type, object value) {
 | 
				
			||||||
			if (value == null || value == DBNull.Value) return Activator.CreateInstance(type);
 | 
								if (value == null || value == DBNull.Value) return Activator.CreateInstance(type);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,280 +0,0 @@
 | 
				
			|||||||
//using FreeSql.DataAnnotations;
 | 
					 | 
				
			||||||
//using FreeSql.Internal.Model;
 | 
					 | 
				
			||||||
//using Newtonsoft.Json.Linq;
 | 
					 | 
				
			||||||
//using Npgsql.LegacyPostgis;
 | 
					 | 
				
			||||||
//using NpgsqlTypes;
 | 
					 | 
				
			||||||
//using System;
 | 
					 | 
				
			||||||
//using System.Collections;
 | 
					 | 
				
			||||||
//using System.Collections.Concurrent;
 | 
					 | 
				
			||||||
//using System.Collections.Generic;
 | 
					 | 
				
			||||||
//using System.Diagnostics;
 | 
					 | 
				
			||||||
//using System.Linq;
 | 
					 | 
				
			||||||
//using System.Net;
 | 
					 | 
				
			||||||
//using System.Net.NetworkInformation;
 | 
					 | 
				
			||||||
//using System.Reflection;
 | 
					 | 
				
			||||||
//using System.Text.RegularExpressions;
 | 
					 | 
				
			||||||
//using System.Threading;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//namespace FreeSql.Internal {
 | 
					 | 
				
			||||||
//	class UtilsReflection {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//		static ConcurrentDictionary<string, TableInfo> _cacheGetTableByEntity = new ConcurrentDictionary<string, TableInfo>();
 | 
					 | 
				
			||||||
//		internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
 | 
					 | 
				
			||||||
//			if (entity.FullName.StartsWith("<>f__AnonymousType")) return null;
 | 
					 | 
				
			||||||
//			if (_cacheGetTableByEntity.TryGetValue($"{common.DbName}-{entity.FullName}", out var trytb)) return trytb; //区分数据库类型缓存
 | 
					 | 
				
			||||||
//			if (common.CodeFirst.GetDbInfo(entity) != null) return null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//			var tbattr = entity.GetCustomAttributes(typeof(TableAttribute), false).LastOrDefault() as TableAttribute;
 | 
					 | 
				
			||||||
//			trytb = new TableInfo();
 | 
					 | 
				
			||||||
//			trytb.Type = entity;
 | 
					 | 
				
			||||||
//			trytb.Properties = entity.GetProperties().ToDictionary(a => a.Name, a => a, StringComparer.CurrentCultureIgnoreCase);
 | 
					 | 
				
			||||||
//			trytb.CsName = entity.Name;
 | 
					 | 
				
			||||||
//			trytb.DbName = (tbattr?.Name ?? entity.Name);
 | 
					 | 
				
			||||||
//			trytb.DbOldName = tbattr?.OldName;
 | 
					 | 
				
			||||||
//			if (common.CodeFirst.IsSyncStructureToLower) {
 | 
					 | 
				
			||||||
//				trytb.DbName = trytb.DbName.ToLower();
 | 
					 | 
				
			||||||
//				trytb.DbOldName = trytb.DbOldName?.ToLower();
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			trytb.SelectFilter = tbattr?.SelectFilter;
 | 
					 | 
				
			||||||
//			foreach (var p in trytb.Properties.Values) {
 | 
					 | 
				
			||||||
//				var tp = common.CodeFirst.GetDbInfo(p.PropertyType);
 | 
					 | 
				
			||||||
//				//if (tp == null) continue;
 | 
					 | 
				
			||||||
//				var colattr = p.GetCustomAttributes(typeof(ColumnAttribute), false).LastOrDefault() as ColumnAttribute;
 | 
					 | 
				
			||||||
//				if (tp == null && colattr == null) continue;
 | 
					 | 
				
			||||||
//				if (colattr == null)
 | 
					 | 
				
			||||||
//					colattr = new ColumnAttribute {
 | 
					 | 
				
			||||||
//						Name = p.Name,
 | 
					 | 
				
			||||||
//						DbType = tp.Value.dbtypeFull,
 | 
					 | 
				
			||||||
//						IsIdentity = false,
 | 
					 | 
				
			||||||
//						IsNullable = tp.Value.isnullable ?? true,
 | 
					 | 
				
			||||||
//						IsPrimary = false,
 | 
					 | 
				
			||||||
//					};
 | 
					 | 
				
			||||||
//				if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)";
 | 
					 | 
				
			||||||
//				colattr.DbType = colattr.DbType.ToUpper();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//				if (tp != null && tp.Value.isnullable == null) colattr.IsNullable = tp.Value.dbtypeFull.Contains("NOT NULL") == false;
 | 
					 | 
				
			||||||
//				if (colattr.DbType?.Contains("NOT NULL") == true) colattr.IsNullable = false;
 | 
					 | 
				
			||||||
//				if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = p.Name;
 | 
					 | 
				
			||||||
//				if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//				if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false) {
 | 
					 | 
				
			||||||
//					colattr.IsNullable = false;
 | 
					 | 
				
			||||||
//					colattr.DbType += " NOT NULL";
 | 
					 | 
				
			||||||
//				}
 | 
					 | 
				
			||||||
//				if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", "");
 | 
					 | 
				
			||||||
//				colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => {
 | 
					 | 
				
			||||||
//					var tmpLt = Regex.Replace(m.Groups[0].Value, @"\s", "");
 | 
					 | 
				
			||||||
//					if (tmpLt.Contains("CHAR")) tmpLt = tmpLt.Replace("CHAR", " CHAR");
 | 
					 | 
				
			||||||
//					if (tmpLt.Contains("BYTE")) tmpLt = tmpLt.Replace("BYTE", " BYTE");
 | 
					 | 
				
			||||||
//					return tmpLt;
 | 
					 | 
				
			||||||
//				});
 | 
					 | 
				
			||||||
//				colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type));
 | 
					 | 
				
			||||||
//				if (colattr.DbDefautValue == null) colattr.DbDefautValue = tp?.defaultValue;
 | 
					 | 
				
			||||||
//				if (colattr.IsNullable == false && colattr.DbDefautValue == null)
 | 
					 | 
				
			||||||
//					colattr.DbDefautValue = Activator.CreateInstance(p.PropertyType.IsNullableType() ? p.PropertyType.GenericTypeArguments.FirstOrDefault() : p.PropertyType);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//				var col = new ColumnInfo {
 | 
					 | 
				
			||||||
//					Table = trytb,
 | 
					 | 
				
			||||||
//					CsName = p.Name,
 | 
					 | 
				
			||||||
//					CsType = p.PropertyType,
 | 
					 | 
				
			||||||
//					Attribute = colattr
 | 
					 | 
				
			||||||
//				};
 | 
					 | 
				
			||||||
//				trytb.Columns.Add(colattr.Name, col);
 | 
					 | 
				
			||||||
//				trytb.ColumnsByCs.Add(p.Name, col);
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
 | 
					 | 
				
			||||||
//			if (trytb.Primarys.Any() == false) {
 | 
					 | 
				
			||||||
//				trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity == true).ToArray();
 | 
					 | 
				
			||||||
//				foreach(var col in trytb.Primarys)
 | 
					 | 
				
			||||||
//					col.Attribute.IsPrimary = true;
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			_cacheGetTableByEntity.TryAdd(entity.FullName, trytb);
 | 
					 | 
				
			||||||
//			return trytb;
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//		internal static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) {
 | 
					 | 
				
			||||||
//			if (string.IsNullOrEmpty(sql) || obj == null) return new T[0];
 | 
					 | 
				
			||||||
//			var ttype = typeof(T);
 | 
					 | 
				
			||||||
//			var type = obj.GetType();
 | 
					 | 
				
			||||||
//			if (type == ttype) return new[] { (T)Convert.ChangeType(obj, type) };
 | 
					 | 
				
			||||||
//			var ret = new List<T>();
 | 
					 | 
				
			||||||
//			var ps = type.GetProperties();
 | 
					 | 
				
			||||||
//			foreach (var p in ps) {
 | 
					 | 
				
			||||||
//				if (sql.IndexOf($"{paramPrefix}{p.Name}", StringComparison.CurrentCultureIgnoreCase) == -1) continue;
 | 
					 | 
				
			||||||
//				var pvalue = p.GetValue(obj);
 | 
					 | 
				
			||||||
//				if (p.PropertyType == ttype) ret.Add((T)Convert.ChangeType(pvalue, ttype));
 | 
					 | 
				
			||||||
//				else ret.Add(constructorParamter(p.Name, p.PropertyType, pvalue));
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			return ret.ToArray();
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//		static Dictionary<Type, bool> dicExecuteArrayRowReadClassOrTuple = new Dictionary<Type, bool> {
 | 
					 | 
				
			||||||
//			[typeof(bool)] = true,
 | 
					 | 
				
			||||||
//			[typeof(sbyte)] = true,
 | 
					 | 
				
			||||||
//			[typeof(short)] = true,
 | 
					 | 
				
			||||||
//			[typeof(int)] = true,
 | 
					 | 
				
			||||||
//			[typeof(long)] = true,
 | 
					 | 
				
			||||||
//			[typeof(byte)] = true,
 | 
					 | 
				
			||||||
//			[typeof(ushort)] = true,
 | 
					 | 
				
			||||||
//			[typeof(uint)] = true,
 | 
					 | 
				
			||||||
//			[typeof(ulong)] = true,
 | 
					 | 
				
			||||||
//			[typeof(double)] = true,
 | 
					 | 
				
			||||||
//			[typeof(float)] = true,
 | 
					 | 
				
			||||||
//			[typeof(decimal)] = true,
 | 
					 | 
				
			||||||
//			[typeof(TimeSpan)] = true,
 | 
					 | 
				
			||||||
//			[typeof(DateTime)] = true,
 | 
					 | 
				
			||||||
//			[typeof(DateTimeOffset)] = true,
 | 
					 | 
				
			||||||
//			[typeof(byte[])] = true,
 | 
					 | 
				
			||||||
//			[typeof(string)] = true,
 | 
					 | 
				
			||||||
//			[typeof(Guid)] = true,
 | 
					 | 
				
			||||||
//			[typeof(MygisPoint)] = true,
 | 
					 | 
				
			||||||
//			[typeof(MygisLineString)] = true,
 | 
					 | 
				
			||||||
//			[typeof(MygisPolygon)] = true,
 | 
					 | 
				
			||||||
//			[typeof(MygisMultiPoint)] = true,
 | 
					 | 
				
			||||||
//			[typeof(MygisMultiLineString)] = true,
 | 
					 | 
				
			||||||
//			[typeof(MygisMultiPolygon)] = true,
 | 
					 | 
				
			||||||
//			[typeof(BitArray)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlPoint)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlLine)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlLSeg)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlBox)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlPath)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlPolygon)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlCircle)] = true,
 | 
					 | 
				
			||||||
//			[typeof((IPAddress Address, int Subnet))] = true,
 | 
					 | 
				
			||||||
//			[typeof(IPAddress)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PhysicalAddress)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlRange<int>)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlRange<long>)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlRange<decimal>)] = true,
 | 
					 | 
				
			||||||
//			[typeof(NpgsqlRange<DateTime>)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisPoint)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisLineString)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisPolygon)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisMultiPoint)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisMultiLineString)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisMultiPolygon)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisGeometry)] = true,
 | 
					 | 
				
			||||||
//			[typeof(PostgisGeometryCollection)] = true,
 | 
					 | 
				
			||||||
//			[typeof(Dictionary<string, string>)] = true,
 | 
					 | 
				
			||||||
//			[typeof(JToken)] = true,
 | 
					 | 
				
			||||||
//			[typeof(JObject)] = true,
 | 
					 | 
				
			||||||
//			[typeof(JArray)] = true,
 | 
					 | 
				
			||||||
//		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//		internal static ConcurrentDictionary<Type, _dicClassConstructorInfo> _dicClassConstructor = new ConcurrentDictionary<Type, _dicClassConstructorInfo>();
 | 
					 | 
				
			||||||
//		internal static ConcurrentDictionary<Type, _dicTupleConstructorInfo> _dicTupleConstructor = new ConcurrentDictionary<Type, _dicTupleConstructorInfo>();
 | 
					 | 
				
			||||||
//		internal class _dicClassConstructorInfo {
 | 
					 | 
				
			||||||
//			public ConstructorInfo Constructor { get; set; }
 | 
					 | 
				
			||||||
//			public PropertyInfo[] Properties { get; set; }
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		internal class _dicTupleConstructorInfo {
 | 
					 | 
				
			||||||
//			public ConstructorInfo Constructor { get; set; }
 | 
					 | 
				
			||||||
//			public Type[] Types { get; set; }
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		internal static (object value, int dataIndex) ExecuteArrayRowReadClassOrTuple(Type type, Dictionary<string, int> names, object[] row, int dataIndex = 0) {
 | 
					 | 
				
			||||||
//			if (type.IsArray) return (GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
 | 
					 | 
				
			||||||
//			var typeGeneric = type;
 | 
					 | 
				
			||||||
//			if (typeGeneric.IsNullableType()) typeGeneric = type.GenericTypeArguments.First();
 | 
					 | 
				
			||||||
//			if (typeGeneric.IsEnum ||
 | 
					 | 
				
			||||||
//				dicExecuteArrayRowReadClassOrTuple.ContainsKey(typeGeneric))
 | 
					 | 
				
			||||||
//				return (GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
 | 
					 | 
				
			||||||
//			if (type.Namespace == "System" && (type.FullName == "System.String" || type.IsValueType)) { //值类型,或者元组
 | 
					 | 
				
			||||||
//				bool isTuple = type.Name.StartsWith("ValueTuple`");
 | 
					 | 
				
			||||||
//				if (isTuple) {
 | 
					 | 
				
			||||||
//					if (_dicTupleConstructor.TryGetValue(type, out var tupleInfo) == false) {
 | 
					 | 
				
			||||||
//						var types = type.GetFields().Select(a => a.FieldType).ToArray();
 | 
					 | 
				
			||||||
//						tupleInfo = new _dicTupleConstructorInfo { Constructor = type.GetConstructor(types), Types = types };
 | 
					 | 
				
			||||||
//						_dicTupleConstructor.AddOrUpdate(type, tupleInfo, (t2, c2) => tupleInfo);
 | 
					 | 
				
			||||||
//					}
 | 
					 | 
				
			||||||
//					var parms = new object[tupleInfo.Types.Length];
 | 
					 | 
				
			||||||
//					for (int a = 0; a < parms.Length; a++) {
 | 
					 | 
				
			||||||
//						var read = ExecuteArrayRowReadClassOrTuple(tupleInfo.Types[a], names, row, dataIndex);
 | 
					 | 
				
			||||||
//						if (read.dataIndex > dataIndex) dataIndex = read.dataIndex;
 | 
					 | 
				
			||||||
//						parms[a] = read.value;
 | 
					 | 
				
			||||||
//					}
 | 
					 | 
				
			||||||
//					return (tupleInfo.Constructor?.Invoke(parms), dataIndex);
 | 
					 | 
				
			||||||
//				}
 | 
					 | 
				
			||||||
//				return (dataIndex >= row.Length || (row[dataIndex] ?? DBNull.Value) == DBNull.Value ? null : GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			if (type == typeof(object) && names != null) {
 | 
					 | 
				
			||||||
//				dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写
 | 
					 | 
				
			||||||
//				var expandodic = (IDictionary<string, object>)expando;
 | 
					 | 
				
			||||||
//				foreach (var name in names)
 | 
					 | 
				
			||||||
//					expandodic.Add(name.Key, row[name.Value]);
 | 
					 | 
				
			||||||
//				return (expando, names.Count);
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			//类注入属性
 | 
					 | 
				
			||||||
//			if (_dicClassConstructor.TryGetValue(type, out var classInfo)== false) {
 | 
					 | 
				
			||||||
//				classInfo = new _dicClassConstructorInfo { Constructor = type.GetConstructor(new Type[0]), Properties = type.GetProperties() };
 | 
					 | 
				
			||||||
//				_dicClassConstructor.TryAdd(type, classInfo);
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			var value = classInfo.Constructor.Invoke(new object[0]);
 | 
					 | 
				
			||||||
//			foreach(var prop in classInfo.Properties) {
 | 
					 | 
				
			||||||
//				var tryidx = dataIndex;
 | 
					 | 
				
			||||||
//				if (names != null && names.TryGetValue(prop.Name, out tryidx) == false) continue;
 | 
					 | 
				
			||||||
//				var read = ExecuteArrayRowReadClassOrTuple(prop.PropertyType, names, row, tryidx);
 | 
					 | 
				
			||||||
//				if (read.dataIndex > dataIndex) dataIndex = read.dataIndex;
 | 
					 | 
				
			||||||
//				prop.SetValue(value, read.value, null);
 | 
					 | 
				
			||||||
//				//FillPropertyValue(value, p.Name, read.value);
 | 
					 | 
				
			||||||
//				//p.SetValue(value, read.value);
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			return (value, dataIndex);
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//		internal static void FillPropertyValue(object info, string memberAccessPath, object value) {
 | 
					 | 
				
			||||||
//			var current = info;
 | 
					 | 
				
			||||||
//			PropertyInfo prop = null;
 | 
					 | 
				
			||||||
//			var members = memberAccessPath.Split('.');
 | 
					 | 
				
			||||||
//			for (var a = 0; a < members.Length; a++) {
 | 
					 | 
				
			||||||
//				var type = current.GetType();
 | 
					 | 
				
			||||||
//				prop = type.GetProperty(members[a], BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
 | 
					 | 
				
			||||||
//				if (prop == null) throw new Exception(string.Concat(type.FullName, " 没有定义属性 ", members[a]));
 | 
					 | 
				
			||||||
//				if (a < members.Length - 1) current = prop.GetValue(current);
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			prop.SetValue(current, GetDataReaderValue(prop.PropertyType, value), null);
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		internal static object GetDataReaderValue(Type type, object value) {
 | 
					 | 
				
			||||||
//			if (value == null || value == DBNull.Value) return null;
 | 
					 | 
				
			||||||
//			if (type.FullName == "System.Byte[]") return value;
 | 
					 | 
				
			||||||
//			if (type.IsArray) {
 | 
					 | 
				
			||||||
//				var elementType = type.GetElementType();
 | 
					 | 
				
			||||||
//				var valueArr = value as Array;
 | 
					 | 
				
			||||||
//				if (elementType == valueArr.GetType().GetElementType()) return value;
 | 
					 | 
				
			||||||
//				var len = valueArr.GetLength(0);
 | 
					 | 
				
			||||||
//				var ret = Array.CreateInstance(elementType, len);
 | 
					 | 
				
			||||||
//				for (var a = 0; a < len; a++) {
 | 
					 | 
				
			||||||
//					var item = valueArr.GetValue(a);
 | 
					 | 
				
			||||||
//					ret.SetValue(GetDataReaderValue(elementType, item), a);
 | 
					 | 
				
			||||||
//				}
 | 
					 | 
				
			||||||
//				return ret;
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			if (type.IsNullableType()) type = type.GenericTypeArguments.First();
 | 
					 | 
				
			||||||
//			if (type.IsEnum) return Enum.Parse(type, string.Concat(value), true);
 | 
					 | 
				
			||||||
//			switch(type.FullName) {
 | 
					 | 
				
			||||||
//				case "System.Guid":
 | 
					 | 
				
			||||||
//					if (value.GetType() != type) return Guid.TryParse(string.Concat(value), out var tryguid) ? tryguid : Guid.Empty;
 | 
					 | 
				
			||||||
//					return value;
 | 
					 | 
				
			||||||
//				case "MygisPoint": return MygisPoint.Parse(string.Concat(value)) as MygisPoint;
 | 
					 | 
				
			||||||
//				case "MygisLineString": return MygisLineString.Parse(string.Concat(value)) as MygisLineString;
 | 
					 | 
				
			||||||
//				case "MygisPolygon": return MygisPolygon.Parse(string.Concat(value)) as MygisPolygon;
 | 
					 | 
				
			||||||
//				case "MygisMultiPoint": return MygisMultiPoint.Parse(string.Concat(value)) as MygisMultiPoint;
 | 
					 | 
				
			||||||
//				case "MygisMultiLineString": return MygisMultiLineString.Parse(string.Concat(value)) as MygisMultiLineString;
 | 
					 | 
				
			||||||
//				case "MygisMultiPolygon": return MygisMultiPolygon.Parse(string.Concat(value)) as MygisMultiPolygon;
 | 
					 | 
				
			||||||
//				case "Newtonsoft.Json.Linq.JToken": return JToken.Parse(string.Concat(value));
 | 
					 | 
				
			||||||
//				case "Newtonsoft.Json.Linq.JObject": return JObject.Parse(string.Concat(value));
 | 
					 | 
				
			||||||
//				case "Newtonsoft.Json.Linq.JArray": return JArray.Parse(string.Concat(value));
 | 
					 | 
				
			||||||
//				case "Npgsql.LegacyPostgis.PostgisGeometry": return value;
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			if (type != value.GetType()) {
 | 
					 | 
				
			||||||
//				if (type.FullName == "System.TimeSpan") return TimeSpan.FromSeconds(double.Parse(value.ToString()));
 | 
					 | 
				
			||||||
//				return Convert.ChangeType(value, type);
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			return value;
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		internal static string GetCsName(string name) {
 | 
					 | 
				
			||||||
//			name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_");
 | 
					 | 
				
			||||||
//			return char.IsLetter(name, 0) ? name : string.Concat("_", name);
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//	}
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
@@ -21,7 +21,7 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
								var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
				
			||||||
@@ -38,7 +38,7 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
								var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
								return _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
				
			||||||
@@ -56,7 +56,7 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
								return await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
								var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
				
			||||||
@@ -47,7 +47,7 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
								var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
				
			||||||
@@ -57,14 +57,14 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
							protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append("CONCAT(");
 | 
								caseWhen.Append("CONCAT(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) caseWhen.Append(", ");
 | 
									if (pkidx > 0) caseWhen.Append(", ");
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append(")");
 | 
								caseWhen.Append(")");
 | 
				
			||||||
@@ -72,14 +72,14 @@ namespace FreeSql.MySql.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
							protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(_table.Primarys.First().CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append("CONCAT(");
 | 
								sb.Append("CONCAT(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) sb.Append(", ");
 | 
									if (pkidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d)));
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append(")");
 | 
								sb.Append(")");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,14 +24,16 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
							static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
				
			||||||
		public override object AddslashesProcessParam(object param) {
 | 
							public override object AddslashesProcessParam(object param, Type mapType) {
 | 
				
			||||||
			if (param == null) return "NULL";
 | 
								if (param == null) return "NULL";
 | 
				
			||||||
 | 
								if (mapType != null && mapType != param.GetType())
 | 
				
			||||||
 | 
									param = Utils.GetDataReaderValue(mapType, param);
 | 
				
			||||||
			if (param is bool || param is bool?)
 | 
								if (param is bool || param is bool?)
 | 
				
			||||||
				return (bool)param ? 1 : 0;
 | 
									return (bool)param ? 1 : 0;
 | 
				
			||||||
			else if (param is string || param is char)
 | 
								else if (param is string || param is char)
 | 
				
			||||||
				return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
									return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
				
			||||||
			else if (param is Enum)
 | 
								else if (param is Enum)
 | 
				
			||||||
				return string.Concat("'", param.ToString().Replace("'", "''"), "'"); //((Enum)param).ToInt64();
 | 
									return string.Concat("'", param.ToString().Replace("'", "''"), "'"); //((Enum)val).ToInt64();
 | 
				
			||||||
			else if (decimal.TryParse(string.Concat(param), out var trydec))
 | 
								else if (decimal.TryParse(string.Concat(param), out var trydec))
 | 
				
			||||||
				return param;
 | 
									return param;
 | 
				
			||||||
			else if (param is DateTime || param is DateTime?)
 | 
								else if (param is DateTime || param is DateTime?)
 | 
				
			||||||
@@ -43,11 +45,10 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			else if (param is IEnumerable) {
 | 
								else if (param is IEnumerable) {
 | 
				
			||||||
				var sb = new StringBuilder();
 | 
									var sb = new StringBuilder();
 | 
				
			||||||
				var ie = param as IEnumerable;
 | 
									var ie = param as IEnumerable;
 | 
				
			||||||
				foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
 | 
									foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
 | 
				
			||||||
				return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
									return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
								return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
				
			||||||
			//if (param is string) return string.Concat('N', nparms[a]);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected override DbCommand CreateCommand() {
 | 
							protected override DbCommand CreateCommand() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,8 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		public MySqlExpression(CommonUtils common) : base(common) { }
 | 
							public MySqlExpression(CommonUtils common) : base(common) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.NodeType) {
 | 
								switch (exp.NodeType) {
 | 
				
			||||||
				case ExpressionType.Convert:
 | 
									case ExpressionType.Convert:
 | 
				
			||||||
					var operandExp = (exp as UnaryExpression)?.Operand;
 | 
										var operandExp = (exp as UnaryExpression)?.Operand;
 | 
				
			||||||
@@ -132,20 +132,20 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Empty": return "''";
 | 
										case "Empty": return "''";
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Length": return $"char_length({left})";
 | 
									case "Length": return $"char_length({left})";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Now": return "now()";
 | 
										case "Now": return "now()";
 | 
				
			||||||
@@ -156,7 +156,7 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Date": return $"cast(date_format({left},'%Y-%m-%d') as datetime)";
 | 
									case "Date": return $"cast(date_format({left},'%Y-%m-%d') as datetime)";
 | 
				
			||||||
				case "TimeOfDay": return $"timestampdiff(microsecond, date_format({left},'%Y-%m-%d'), {left})";
 | 
									case "TimeOfDay": return $"timestampdiff(microsecond, date_format({left},'%Y-%m-%d'), {left})";
 | 
				
			||||||
@@ -173,7 +173,7 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Zero": return "0";
 | 
										case "Zero": return "0";
 | 
				
			||||||
@@ -182,7 +182,7 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Days": return $"(({left}) div {(long)1000000 * 60 * 60 * 24})";
 | 
									case "Days": return $"(({left}) div {(long)1000000 * 60 * 60 * 24})";
 | 
				
			||||||
				case "Hours": return $"(({left}) div {(long)1000000 * 60 * 60} mod 24)";
 | 
									case "Hours": return $"(({left}) div {(long)1000000 * 60 * 60} mod 24)";
 | 
				
			||||||
@@ -199,8 +199,8 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "IsNullOrEmpty":
 | 
										case "IsNullOrEmpty":
 | 
				
			||||||
@@ -272,8 +272,8 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.Method.Name) {
 | 
								switch (exp.Method.Name) {
 | 
				
			||||||
				case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
									case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
				
			||||||
				case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
									case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
				
			||||||
@@ -298,8 +298,8 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
 | 
										case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
 | 
				
			||||||
@@ -341,8 +341,8 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
										case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
				
			||||||
@@ -371,8 +371,8 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
 | 
										case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,6 +49,12 @@ namespace FreeSql.MySql {
 | 
				
			|||||||
				return nametrim; //原生SQL
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
			return $"`{nametrim.Trim('`').Replace(".", "`.`")}`";
 | 
								return $"`{nametrim.Trim('`').Replace(".", "`.`")}`";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							internal override string TrimQuoteSqlName(string name) {
 | 
				
			||||||
 | 
								var nametrim = name.Trim();
 | 
				
			||||||
 | 
								if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
 | 
				
			||||||
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
 | 
								return $"{nametrim.Trim('`').Replace("`.`", ".").Replace(".`", ".")}";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		internal override string QuoteParamterName(string name) => $"?{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
							internal override string QuoteParamterName(string name) => $"?{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
				
			||||||
		internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
 | 
							internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
 | 
				
			||||||
		internal override string StringConcat(string[] objs, Type[] types) => $"concat({string.Join(", ", objs)})";
 | 
							internal override string StringConcat(string[] objs, Type[] types) => $"concat({string.Join(", ", objs)})";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,17 +60,14 @@ namespace FreeSql.Oracle.Curd {
 | 
				
			|||||||
				foreach (var col in _table.Columns.Values) {
 | 
									foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
					if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
 | 
										if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
 | 
				
			||||||
						if (colidx2 > 0) sb.Append(", ");
 | 
											if (colidx2 > 0) sb.Append(", ");
 | 
				
			||||||
						object val = null;
 | 
											object val = col.GetMapValue(d);
 | 
				
			||||||
						if (_table.Properties.TryGetValue(col.CsName, out var tryp)) {
 | 
											if (col.Attribute.IsPrimary && col.Attribute.MapType.NullableTypeOrThis() == typeof(Guid) && (val == null || (Guid)val == Guid.Empty))
 | 
				
			||||||
							val = tryp.GetValue(d);
 | 
												col.SetMapValue(d, val = FreeUtil.NewMongodbId());
 | 
				
			||||||
							if (col.Attribute.IsPrimary && (col.CsType == typeof(Guid) || col.CsType == typeof(Guid?))
 | 
					 | 
				
			||||||
								&& (val == null || (Guid)val == Guid.Empty)) tryp.SetValue(d, val = FreeUtil.NewMongodbId());
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						if (_noneParameter)
 | 
											if (_noneParameter)
 | 
				
			||||||
							sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.CsType, val));
 | 
												sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val));
 | 
				
			||||||
						else {
 | 
											else {
 | 
				
			||||||
							sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}")));
 | 
												sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}")));
 | 
				
			||||||
							_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col.CsType, val);
 | 
												_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col.Attribute.MapType, val);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						++colidx2;
 | 
											++colidx2;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -92,7 +89,7 @@ namespace FreeSql.Oracle.Curd {
 | 
				
			|||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name);
 | 
								var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name);
 | 
				
			||||||
			var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.CsType, 0) as OracleParameter;
 | 
								var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.Attribute.MapType, 0) as OracleParameter;
 | 
				
			||||||
			identParam.Direction = ParameterDirection.Output;
 | 
								identParam.Direction = ParameterDirection.Output;
 | 
				
			||||||
			_orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}", _params.Concat(new[] { identParam }).ToArray());
 | 
								_orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}", _params.Concat(new[] { identParam }).ToArray());
 | 
				
			||||||
			return long.TryParse(string.Concat(identParam.Value), out var trylng) ? trylng : 0;
 | 
								return long.TryParse(string.Concat(identParam.Value), out var trylng) ? trylng : 0;
 | 
				
			||||||
@@ -106,7 +103,7 @@ namespace FreeSql.Oracle.Curd {
 | 
				
			|||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name);
 | 
								var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name);
 | 
				
			||||||
			var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.CsType, 0) as OracleParameter;
 | 
								var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.Attribute.MapType, 0) as OracleParameter;
 | 
				
			||||||
			identParam.Direction = ParameterDirection.Output;
 | 
								identParam.Direction = ParameterDirection.Output;
 | 
				
			||||||
			await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}", _params.Concat(new[] { identParam }).ToArray());
 | 
								await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}", _params.Concat(new[] { identParam }).ToArray());
 | 
				
			||||||
			return long.TryParse(string.Concat(identParam.Value), out var trylng) ? trylng : 0;
 | 
								return long.TryParse(string.Concat(identParam.Value), out var trylng) ? trylng : 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,14 +30,14 @@ namespace FreeSql.Oracle.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
							protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append("(");
 | 
								caseWhen.Append("(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) caseWhen.Append(" || ");
 | 
									if (pkidx > 0) caseWhen.Append(" || ");
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append(")");
 | 
								caseWhen.Append(")");
 | 
				
			||||||
@@ -45,14 +45,14 @@ namespace FreeSql.Oracle.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
							protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(_table.Primarys.First().CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append("(");
 | 
								sb.Append("(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) sb.Append(" || ");
 | 
									if (pkidx > 0) sb.Append(" || ");
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d)));
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append(")");
 | 
								sb.Append(")");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,10 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
							static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
				
			||||||
		public override object AddslashesProcessParam(object param) {
 | 
							public override object AddslashesProcessParam(object param, Type mapType) {
 | 
				
			||||||
			if (param == null) return "NULL";
 | 
								if (param == null) return "NULL";
 | 
				
			||||||
 | 
								if (mapType != null && mapType != param.GetType())
 | 
				
			||||||
 | 
									param = Utils.GetDataReaderValue(mapType, param);
 | 
				
			||||||
			if (param is bool || param is bool?)
 | 
								if (param is bool || param is bool?)
 | 
				
			||||||
				return (bool)param ? 1 : 0;
 | 
									return (bool)param ? 1 : 0;
 | 
				
			||||||
			else if (param is string || param is char)
 | 
								else if (param is string || param is char)
 | 
				
			||||||
@@ -40,7 +42,7 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			else if (param is IEnumerable) {
 | 
								else if (param is IEnumerable) {
 | 
				
			||||||
				var sb = new StringBuilder();
 | 
									var sb = new StringBuilder();
 | 
				
			||||||
				var ie = param as IEnumerable;
 | 
									var ie = param as IEnumerable;
 | 
				
			||||||
				foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
 | 
									foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
 | 
				
			||||||
				return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
									return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
								return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,8 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		public OracleExpression(CommonUtils common) : base(common) { }
 | 
							public OracleExpression(CommonUtils common) : base(common) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.NodeType) {
 | 
								switch (exp.NodeType) {
 | 
				
			||||||
				case ExpressionType.Convert:
 | 
									case ExpressionType.Convert:
 | 
				
			||||||
					var operandExp = (exp as UnaryExpression)?.Operand;
 | 
										var operandExp = (exp as UnaryExpression)?.Operand;
 | 
				
			||||||
@@ -132,20 +132,20 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Empty": return "''";
 | 
										case "Empty": return "''";
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Length": return $"length({left})";
 | 
									case "Length": return $"length({left})";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Now": return "systimestamp";
 | 
										case "Now": return "systimestamp";
 | 
				
			||||||
@@ -156,7 +156,7 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Date": return $"trunc({left})";
 | 
									case "Date": return $"trunc({left})";
 | 
				
			||||||
				case "TimeOfDay": return $"({left}-trunc({left}))";
 | 
									case "TimeOfDay": return $"({left}-trunc({left}))";
 | 
				
			||||||
@@ -173,7 +173,7 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Zero": return "numtodsinterval(0,'second')";
 | 
										case "Zero": return "numtodsinterval(0,'second')";
 | 
				
			||||||
@@ -182,7 +182,7 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Days": return $"extract(day from {left})";
 | 
									case "Days": return $"extract(day from {left})";
 | 
				
			||||||
				case "Hours": return $"extract(hour from {left})";
 | 
									case "Hours": return $"extract(hour from {left})";
 | 
				
			||||||
@@ -199,8 +199,8 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "IsNullOrEmpty":
 | 
										case "IsNullOrEmpty":
 | 
				
			||||||
@@ -272,8 +272,8 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.Method.Name) {
 | 
								switch (exp.Method.Name) {
 | 
				
			||||||
				case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
									case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
				
			||||||
				case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
									case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
				
			||||||
@@ -299,8 +299,8 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))";
 | 
										case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))";
 | 
				
			||||||
@@ -342,8 +342,8 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))";
 | 
										case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))";
 | 
				
			||||||
@@ -372,8 +372,8 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					//case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
 | 
										//case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,6 +44,12 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
				return nametrim; //原生SQL
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
			return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
 | 
								return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							internal override string TrimQuoteSqlName(string name) {
 | 
				
			||||||
 | 
								var nametrim = name.Trim();
 | 
				
			||||||
 | 
								if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
 | 
				
			||||||
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
 | 
								return $"{nametrim.Trim('"').Replace("\".\"", ".").Replace(".\"", ".")}";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		internal override string QuoteParamterName(string name) => $":{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
							internal override string QuoteParamterName(string name) => $":{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
				
			||||||
		internal override string IsNull(string sql, object value) => $"nvl({sql}, {value})";
 | 
							internal override string IsNull(string sql, object value) => $"nvl({sql}, {value})";
 | 
				
			||||||
		internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
 | 
							internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
								var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
				
			||||||
@@ -38,7 +38,7 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
								var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.ToArray());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,7 +53,7 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
								return _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
				
			||||||
@@ -68,7 +68,7 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
								return await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
								var ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
				
			||||||
@@ -47,7 +47,7 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
								var ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
 | 
				
			||||||
@@ -57,14 +57,14 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
							protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append("(");
 | 
								caseWhen.Append("(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) caseWhen.Append(" || ");
 | 
									if (pkidx > 0) caseWhen.Append(" || ");
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(pk.Attribute.Name))).Append("::varchar");
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name))).Append("::varchar");
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append(")");
 | 
								caseWhen.Append(")");
 | 
				
			||||||
@@ -72,14 +72,14 @@ namespace FreeSql.PostgreSQL.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
							protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(_table.Primarys.First().CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append("(");
 | 
								sb.Append("(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) sb.Append(" || ");
 | 
									if (pkidx > 0) sb.Append(" || ");
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null)).Append("::varchar");
 | 
									sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d))).Append("::varchar");
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append(")");
 | 
								sb.Append(")");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,9 +26,11 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
							static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
				
			||||||
		public override object AddslashesProcessParam(object param) {
 | 
							public override object AddslashesProcessParam(object param, Type mapType) {
 | 
				
			||||||
			bool isdic = false;
 | 
					 | 
				
			||||||
			if (param == null) return "NULL";
 | 
								if (param == null) return "NULL";
 | 
				
			||||||
 | 
								if (mapType != null && mapType != param.GetType())
 | 
				
			||||||
 | 
									param = Utils.GetDataReaderValue(mapType, param);
 | 
				
			||||||
 | 
								bool isdic = false;
 | 
				
			||||||
			if (param is bool || param is bool?)
 | 
								if (param is bool || param is bool?)
 | 
				
			||||||
				return (bool)param ? "'t'" : "'f'";
 | 
									return (bool)param ? "'t'" : "'f'";
 | 
				
			||||||
			else if (param is string || param is char)
 | 
								else if (param is string || param is char)
 | 
				
			||||||
@@ -57,12 +59,10 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			} else if (param is IEnumerable) {
 | 
								} else if (param is IEnumerable) {
 | 
				
			||||||
				var sb = new StringBuilder();
 | 
									var sb = new StringBuilder();
 | 
				
			||||||
				var ie = param as IEnumerable;
 | 
									var ie = param as IEnumerable;
 | 
				
			||||||
				foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
 | 
									foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
 | 
				
			||||||
				return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
									return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
				
			||||||
			}else {
 | 
					 | 
				
			||||||
				return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
					 | 
				
			||||||
				//if (param is string) return string.Concat('N', nparms[a]);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected override DbCommand CreateCommand() {
 | 
							protected override DbCommand CreateCommand() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,8 +13,8 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		public PostgreSQLExpression(CommonUtils common) : base(common) { }
 | 
							public PostgreSQLExpression(CommonUtils common) : base(common) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.NodeType) {
 | 
								switch (exp.NodeType) {
 | 
				
			||||||
				case ExpressionType.Convert:
 | 
									case ExpressionType.Convert:
 | 
				
			||||||
					var operandExp = (exp as UnaryExpression)?.Operand;
 | 
										var operandExp = (exp as UnaryExpression)?.Operand;
 | 
				
			||||||
@@ -227,20 +227,20 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Empty": return "''";
 | 
										case "Empty": return "''";
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Length": return $"char_length({left})";
 | 
									case "Length": return $"char_length({left})";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Now": return "current_timestamp";
 | 
										case "Now": return "current_timestamp";
 | 
				
			||||||
@@ -251,7 +251,7 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Date": return $"({left})::date";
 | 
									case "Date": return $"({left})::date";
 | 
				
			||||||
				case "TimeOfDay": return $"(extract(epoch from ({left})::time)*1000000)";
 | 
									case "TimeOfDay": return $"(extract(epoch from ({left})::time)*1000000)";
 | 
				
			||||||
@@ -268,7 +268,7 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Zero": return "0";
 | 
										case "Zero": return "0";
 | 
				
			||||||
@@ -277,7 +277,7 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Days": return $"floor(({left})/{(long)1000000 * 60 * 60 * 24})";
 | 
									case "Days": return $"floor(({left})/{(long)1000000 * 60 * 60 * 24})";
 | 
				
			||||||
				case "Hours": return $"floor(({left})/{(long)1000000 * 60 * 60}%24)";
 | 
									case "Hours": return $"floor(({left})/{(long)1000000 * 60 * 60}%24)";
 | 
				
			||||||
@@ -294,8 +294,8 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "IsNullOrEmpty":
 | 
										case "IsNullOrEmpty":
 | 
				
			||||||
@@ -369,8 +369,8 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.Method.Name) {
 | 
								switch (exp.Method.Name) {
 | 
				
			||||||
				case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
									case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
				
			||||||
				case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
									case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
				
			||||||
@@ -395,8 +395,8 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"extract(epoch from ({getExp(exp.Arguments[0])})::timestamp-({getExp(exp.Arguments[1])})::timestamp)";
 | 
										case "Compare": return $"extract(epoch from ({getExp(exp.Arguments[0])})::timestamp-({getExp(exp.Arguments[1])})::timestamp)";
 | 
				
			||||||
@@ -438,8 +438,8 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
										case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
				
			||||||
@@ -468,8 +468,8 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::varchar not in ('0','false','f','no'))";
 | 
										case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::varchar not in ('0','false','f','no'))";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,6 +103,12 @@ namespace FreeSql.PostgreSQL {
 | 
				
			|||||||
				return nametrim; //原生SQL
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
			return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
 | 
								return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							internal override string TrimQuoteSqlName(string name) {
 | 
				
			||||||
 | 
								var nametrim = name.Trim();
 | 
				
			||||||
 | 
								if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
 | 
				
			||||||
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
 | 
								return $"{nametrim.Trim('"').Replace("\".\"", ".").Replace(".\"", ".")}";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
							internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
				
			||||||
		internal override string IsNull(string sql, object value) => $"coalesce({sql}, {value})";
 | 
							internal override string IsNull(string sql, object value) => $"coalesce({sql}, {value})";
 | 
				
			||||||
		internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
 | 
							internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append("DELETED.").Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append("DELETED.").Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -43,7 +43,7 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append("DELETED.").Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append("DELETED.").Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,7 +44,7 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,7 +64,7 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,7 +52,7 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
			var colidx = 0;
 | 
								var colidx = 0;
 | 
				
			||||||
			foreach (var col in _table.Columns.Values) {
 | 
								foreach (var col in _table.Columns.Values) {
 | 
				
			||||||
				if (colidx > 0) sb.Append(", ");
 | 
									if (colidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.QuoteReadColumn(col.CsType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
									sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
 | 
				
			||||||
				++colidx;
 | 
									++colidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -68,14 +68,14 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
							protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append("(");
 | 
								caseWhen.Append("(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) caseWhen.Append(", ");
 | 
									if (pkidx > 0) caseWhen.Append(", ");
 | 
				
			||||||
				caseWhen.Append("cast(").Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(pk.Attribute.Name))).Append(" as varchar)");
 | 
									caseWhen.Append("cast(").Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name))).Append(" as varchar)");
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append(")");
 | 
								caseWhen.Append(")");
 | 
				
			||||||
@@ -83,13 +83,13 @@ namespace FreeSql.SqlServer.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
							protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(_table.Primarys.First().CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) sb.Append(", ");
 | 
									if (pkidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append("cast(").Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null)).Append(" as varchar)");
 | 
									sb.Append("cast(").Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d))).Append(" as varchar)");
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,10 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
							static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
				
			||||||
		public override object AddslashesProcessParam(object param) {
 | 
							public override object AddslashesProcessParam(object param, Type mapType) {
 | 
				
			||||||
			if (param == null) return "NULL";
 | 
								if (param == null) return "NULL";
 | 
				
			||||||
 | 
								if (mapType != null && mapType != param.GetType())
 | 
				
			||||||
 | 
									param = Utils.GetDataReaderValue(mapType, param);
 | 
				
			||||||
			if (param is bool || param is bool?)
 | 
								if (param is bool || param is bool?)
 | 
				
			||||||
				return (bool)param ? 1 : 0;
 | 
									return (bool)param ? 1 : 0;
 | 
				
			||||||
			else if (param is string || param is char)
 | 
								else if (param is string || param is char)
 | 
				
			||||||
@@ -39,19 +41,17 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			} else if (param is DateTimeOffset || param is DateTimeOffset?) {
 | 
								} else if (param is DateTimeOffset || param is DateTimeOffset?) {
 | 
				
			||||||
				if (param.Equals(DateTimeOffset.MinValue) == true) param = new DateTimeOffset(new DateTime(1970, 1, 1), TimeSpan.Zero);
 | 
									if (param.Equals(DateTimeOffset.MinValue) == true) param = new DateTimeOffset(new DateTime(1970, 1, 1), TimeSpan.Zero);
 | 
				
			||||||
				return string.Concat("'", ((DateTimeOffset)param).ToString("yyyy-MM-dd HH:mm:ss.fff zzzz"), "'");
 | 
									return string.Concat("'", ((DateTimeOffset)param).ToString("yyyy-MM-dd HH:mm:ss.fff zzzz"), "'");
 | 
				
			||||||
			}
 | 
								} else if (param is TimeSpan || param is TimeSpan?)
 | 
				
			||||||
			else if (param is TimeSpan || param is TimeSpan?)
 | 
					 | 
				
			||||||
				return ((TimeSpan)param).TotalSeconds;
 | 
									return ((TimeSpan)param).TotalSeconds;
 | 
				
			||||||
			else if (param is IEnumerable) {
 | 
								else if (param is IEnumerable) {
 | 
				
			||||||
				var sb = new StringBuilder();
 | 
									var sb = new StringBuilder();
 | 
				
			||||||
				var ie = param as IEnumerable;
 | 
									var ie = param as IEnumerable;
 | 
				
			||||||
				foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
 | 
									foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
 | 
				
			||||||
				return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
									return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
				
			||||||
			} else {
 | 
								}
 | 
				
			||||||
			return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
								return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
				
			||||||
			//if (param is string) return string.Concat('N', nparms[a]);
 | 
								//if (param is string) return string.Concat('N', nparms[a]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected override DbCommand CreateCommand() {
 | 
							protected override DbCommand CreateCommand() {
 | 
				
			||||||
			return new SqlCommand();
 | 
								return new SqlCommand();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,8 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		public SqlServerExpression(CommonUtils common) : base(common) { }
 | 
							public SqlServerExpression(CommonUtils common) : base(common) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.NodeType) {
 | 
								switch (exp.NodeType) {
 | 
				
			||||||
				case ExpressionType.Convert:
 | 
									case ExpressionType.Convert:
 | 
				
			||||||
					var operandExp = (exp as UnaryExpression)?.Operand;
 | 
										var operandExp = (exp as UnaryExpression)?.Operand;
 | 
				
			||||||
@@ -135,20 +135,20 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Empty": return "''";
 | 
										case "Empty": return "''";
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Length": return $"len({left})";
 | 
									case "Length": return $"len({left})";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Now": return "getdate()";
 | 
										case "Now": return "getdate()";
 | 
				
			||||||
@@ -159,7 +159,7 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Date": return $"convert(char(10),{left},120)";
 | 
									case "Date": return $"convert(char(10),{left},120)";
 | 
				
			||||||
				case "TimeOfDay": return $"datediff(second, convert(char(10),{left},120), {left})";
 | 
									case "TimeOfDay": return $"datediff(second, convert(char(10),{left},120), {left})";
 | 
				
			||||||
@@ -176,7 +176,7 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Zero": return "0";
 | 
										case "Zero": return "0";
 | 
				
			||||||
@@ -185,7 +185,7 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Days": return $"floor(({left})/{60 * 60 * 24})";
 | 
									case "Days": return $"floor(({left})/{60 * 60 * 24})";
 | 
				
			||||||
				case "Hours": return $"floor(({left})/{60 * 60}%24)";
 | 
									case "Hours": return $"floor(({left})/{60 * 60}%24)";
 | 
				
			||||||
@@ -202,8 +202,8 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "IsNullOrEmpty":
 | 
										case "IsNullOrEmpty":
 | 
				
			||||||
@@ -257,8 +257,8 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.Method.Name) {
 | 
								switch (exp.Method.Name) {
 | 
				
			||||||
				case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
									case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
				
			||||||
				case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
									case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
				
			||||||
@@ -283,8 +283,8 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
 | 
										case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
 | 
				
			||||||
@@ -326,8 +326,8 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
										case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
				
			||||||
@@ -356,8 +356,8 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "ToBoolean": return $"(cast({getExp(exp.Arguments[0])} as varchar) not in ('0','false'))";
 | 
										case "ToBoolean": return $"(cast({getExp(exp.Arguments[0])} as varchar) not in ('0','false'))";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,12 @@ namespace FreeSql.SqlServer {
 | 
				
			|||||||
				return nametrim; //原生SQL
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
			return $"[{nametrim.TrimStart('[').TrimEnd(']').Replace(".", "].[")}]";
 | 
								return $"[{nametrim.TrimStart('[').TrimEnd(']').Replace(".", "].[")}]";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							internal override string TrimQuoteSqlName(string name) {
 | 
				
			||||||
 | 
								var nametrim = name.Trim();
 | 
				
			||||||
 | 
								if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
 | 
				
			||||||
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
 | 
								return $"{nametrim.TrimStart('[').TrimEnd(']').Replace("].[", ".").Replace(".[", ".")}";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
							internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
				
			||||||
		internal override string IsNull(string sql, object value) => $"isnull({sql}, {value})";
 | 
							internal override string IsNull(string sql, object value) => $"isnull({sql}, {value})";
 | 
				
			||||||
		internal override string StringConcat(string[] objs, Type[] types) {
 | 
							internal override string StringConcat(string[] objs, Type[] types) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,14 +30,14 @@ namespace FreeSql.Sqlite.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
							protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append("CONCAT(");
 | 
								caseWhen.Append("CONCAT(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) caseWhen.Append(", ");
 | 
									if (pkidx > 0) caseWhen.Append(", ");
 | 
				
			||||||
				caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
 | 
									caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			caseWhen.Append(")");
 | 
								caseWhen.Append(")");
 | 
				
			||||||
@@ -45,14 +45,14 @@ namespace FreeSql.Sqlite.Curd {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
							protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
 | 
				
			||||||
			if (_table.Primarys.Length == 1) {
 | 
								if (_table.Primarys.Length == 1) {
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(_table.Primarys.First().CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append("CONCAT(");
 | 
								sb.Append("CONCAT(");
 | 
				
			||||||
			var pkidx = 0;
 | 
								var pkidx = 0;
 | 
				
			||||||
			foreach (var pk in _table.Primarys) {
 | 
								foreach (var pk in _table.Primarys) {
 | 
				
			||||||
				if (pkidx > 0) sb.Append(", ");
 | 
									if (pkidx > 0) sb.Append(", ");
 | 
				
			||||||
				sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null));
 | 
									sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d)));
 | 
				
			||||||
				++pkidx;
 | 
									++pkidx;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sb.Append(")");
 | 
								sb.Append(")");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,10 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
							static DateTime dt1970 = new DateTime(1970, 1, 1);
 | 
				
			||||||
		public override object AddslashesProcessParam(object param) {
 | 
							public override object AddslashesProcessParam(object param, Type mapType) {
 | 
				
			||||||
			if (param == null) return "NULL";
 | 
								if (param == null) return "NULL";
 | 
				
			||||||
 | 
								if (mapType != null && mapType != param.GetType())
 | 
				
			||||||
 | 
									param = Utils.GetDataReaderValue(mapType, param);
 | 
				
			||||||
			if (param is bool || param is bool?)
 | 
								if (param is bool || param is bool?)
 | 
				
			||||||
				return (bool)param ? 1 : 0;
 | 
									return (bool)param ? 1 : 0;
 | 
				
			||||||
			else if (param is string || param is char)
 | 
								else if (param is string || param is char)
 | 
				
			||||||
@@ -40,11 +42,10 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			else if (param is IEnumerable) {
 | 
								else if (param is IEnumerable) {
 | 
				
			||||||
				var sb = new StringBuilder();
 | 
									var sb = new StringBuilder();
 | 
				
			||||||
				var ie = param as IEnumerable;
 | 
									var ie = param as IEnumerable;
 | 
				
			||||||
				foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
 | 
									foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
 | 
				
			||||||
				return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
									return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
								return string.Concat("'", param.ToString().Replace("'", "''"), "'");
 | 
				
			||||||
			//if (param is string) return string.Concat('N', nparms[a]);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected override DbCommand CreateCommand() {
 | 
							protected override DbCommand CreateCommand() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,8 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		public SqliteExpression(CommonUtils common) : base(common) { }
 | 
							public SqliteExpression(CommonUtils common) : base(common) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.NodeType) {
 | 
								switch (exp.NodeType) {
 | 
				
			||||||
				case ExpressionType.Convert:
 | 
									case ExpressionType.Convert:
 | 
				
			||||||
					var operandExp = (exp as UnaryExpression)?.Operand;
 | 
										var operandExp = (exp as UnaryExpression)?.Operand;
 | 
				
			||||||
@@ -132,20 +132,20 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Empty": return "''";
 | 
										case "Empty": return "''";
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Length": return $"length({left})";
 | 
									case "Length": return $"length({left})";
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Now": return "datetime(current_timestamp,'localtime')";
 | 
										case "Now": return "datetime(current_timestamp,'localtime')";
 | 
				
			||||||
@@ -156,7 +156,7 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Date": return $"date({left})";
 | 
									case "Date": return $"date({left})";
 | 
				
			||||||
				case "TimeOfDay": return $"strftime('%s',{left})";
 | 
									case "TimeOfDay": return $"strftime('%s',{left})";
 | 
				
			||||||
@@ -173,7 +173,7 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			if (exp.Expression == null) {
 | 
								if (exp.Expression == null) {
 | 
				
			||||||
				switch (exp.Member.Name) {
 | 
									switch (exp.Member.Name) {
 | 
				
			||||||
					case "Zero": return "0";
 | 
										case "Zero": return "0";
 | 
				
			||||||
@@ -182,7 +182,7 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return null;
 | 
									return null;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								var left = ExpressionLambdaToSql(exp.Expression, tsc);
 | 
				
			||||||
			switch (exp.Member.Name) {
 | 
								switch (exp.Member.Name) {
 | 
				
			||||||
				case "Days": return $"floor(({left})/{60 * 60 * 24})";
 | 
									case "Days": return $"floor(({left})/{60 * 60 * 24})";
 | 
				
			||||||
				case "Hours": return $"floor(({left})/{60 * 60}%24)";
 | 
									case "Hours": return $"floor(({left})/{60 * 60}%24)";
 | 
				
			||||||
@@ -199,8 +199,8 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "IsNullOrEmpty":
 | 
										case "IsNullOrEmpty":
 | 
				
			||||||
@@ -277,8 +277,8 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			switch (exp.Method.Name) {
 | 
								switch (exp.Method.Name) {
 | 
				
			||||||
				case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
									case "Abs": return $"abs({getExp(exp.Arguments[0])})";
 | 
				
			||||||
				case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
									case "Sign": return $"sign({getExp(exp.Arguments[0])})";
 | 
				
			||||||
@@ -303,8 +303,8 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"(strftime('%s',{getExp(exp.Arguments[0])}) -strftime('%s',{getExp(exp.Arguments[1])}))";
 | 
										case "Compare": return $"(strftime('%s',{getExp(exp.Arguments[0])}) -strftime('%s',{getExp(exp.Arguments[1])}))";
 | 
				
			||||||
@@ -346,8 +346,8 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
										case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
 | 
				
			||||||
@@ -376,8 +376,8 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
								throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName, bool isDisableDiyParse, ExpressionStyle style) {
 | 
							internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
 | 
				
			||||||
			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName, isDisableDiyParse, style);
 | 
								Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
 | 
				
			||||||
			if (exp.Object == null) {
 | 
								if (exp.Object == null) {
 | 
				
			||||||
				switch (exp.Method.Name) {
 | 
									switch (exp.Method.Name) {
 | 
				
			||||||
					case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
 | 
										case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,6 +59,12 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
				return nametrim; //原生SQL
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
			return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
 | 
								return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							internal override string TrimQuoteSqlName(string name) {
 | 
				
			||||||
 | 
								var nametrim = name.Trim();
 | 
				
			||||||
 | 
								if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
 | 
				
			||||||
 | 
									return nametrim; //原生SQL
 | 
				
			||||||
 | 
								return $"{nametrim.Trim('"').Replace("\".\"", ".").Replace(".\"", ".")}";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
							internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
 | 
				
			||||||
		internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
 | 
							internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
 | 
				
			||||||
		internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
 | 
							internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user