mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-01 00:05:28 +08:00 
			
		
		
		
	拆分 FreeSql 按需引用
This commit is contained in:
		| @@ -24,7 +24,6 @@ namespace efcore_to_freesql | ||||
|  | ||||
| 			Fsql = new FreeSql.FreeSqlBuilder() | ||||
| 				.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10") | ||||
| 				.UseLogger(loggerFactory.CreateLogger<IFreeSql>()) | ||||
| 				.UseAutoSyncStructure(true) | ||||
| 				.Build(); | ||||
|  | ||||
| @@ -69,10 +68,6 @@ namespace efcore_to_freesql | ||||
|  | ||||
|         public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) | ||||
|         { | ||||
| 			Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); | ||||
| 			Console.OutputEncoding = Encoding.GetEncoding("GB2312"); | ||||
| 			Console.InputEncoding = Encoding.GetEncoding("GB2312"); | ||||
|  | ||||
| 			loggerFactory.AddConsole(Configuration.GetSection("Logging")); | ||||
| 			loggerFactory.AddDebug(); | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,6 @@ namespace restful { | ||||
|  | ||||
| 			Fsql = new FreeSql.FreeSqlBuilder() | ||||
| 				.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10") | ||||
| 				.UseLogger(loggerFactory.CreateLogger<IFreeSql>()) | ||||
| 				.UseAutoSyncStructure(true) | ||||
| 				.Build(); | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,28 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<Version>0.6.1</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 扩展包,可实现【延时加载】属性.</Description> | ||||
| 		<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl> | ||||
| 		<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl> | ||||
| 		<RepositoryType>git</RepositoryType> | ||||
| 		<PackageLicenseExpression>MIT</PackageLicenseExpression> | ||||
| 		<PackageTags>FreeSql;ORM</PackageTags> | ||||
| 		<PackageId>$(AssemblyName)</PackageId> | ||||
| 		<Title>$(AssemblyName)</Title> | ||||
| 		<IsPackable>true</IsPackable> | ||||
| 		<GenerateAssemblyInfo>true</GenerateAssemblyInfo> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="CS-Script.Core" Version="1.1.1" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\..\FreeSql\FreeSql.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| </Project> | ||||
| @@ -0,0 +1,30 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FreeSql.Extensions.LazyLoading { | ||||
|  | ||||
| 	public class LazyLoadingComplier { | ||||
|  | ||||
| 		internal static Lazy<CSScriptLib.RoslynEvaluator> _compiler = new Lazy<CSScriptLib.RoslynEvaluator>(() => { | ||||
| 			//var dlls = Directory.GetFiles(Directory.GetParent(Type.GetType("IFreeSql, FreeSql").Assembly.Location).FullName, "*.dll"); | ||||
| 			var compiler = new CSScriptLib.RoslynEvaluator(); | ||||
| 			compiler.DisableReferencingFromCode = false; | ||||
| 			//compiler.DebugBuild = true; | ||||
| 			//foreach (var dll in dlls) { | ||||
| 			//	Console.WriteLine(dll); | ||||
| 			//	var ass = Assembly.LoadFile(dll); | ||||
| 			//	compiler.ReferenceAssembly(ass); | ||||
| 			//} | ||||
| 			compiler | ||||
| 				.ReferenceAssemblyOf<IFreeSql>() | ||||
| 				.ReferenceDomainAssemblies(); | ||||
| 			return compiler; | ||||
| 		}); | ||||
|  | ||||
| 		public static Assembly CompileCode(string cscode) { | ||||
| 			return _compiler.Value.CompileCode(cscode); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -14,7 +14,13 @@ | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj" /> | ||||
|     <ProjectReference Include="..\FreeSql\FreeSql.csproj" /> | ||||
|     <ProjectReference Include="..\Providers\FreeSql.Provider.MySql\FreeSql.Provider.MySql.csproj" /> | ||||
|     <ProjectReference Include="..\Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj" /> | ||||
|     <ProjectReference Include="..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" /> | ||||
|     <ProjectReference Include="..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" /> | ||||
|     <ProjectReference Include="..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
|  | ||||
| @@ -8,32 +7,27 @@ public class g { | ||||
|  | ||||
| 	public static IFreeSql mysql = new FreeSql.FreeSqlBuilder() | ||||
| 		.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=100") | ||||
| 		.UseLogger(new LoggerFactory().CreateLogger("FreeSql.MySql")) | ||||
| 		.UseAutoSyncStructure(false) | ||||
| 		.Build(); | ||||
|  | ||||
| 	//public static IFreeSql sqlserver = new FreeSql.FreeSqlBuilder() | ||||
| 	//	.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=cms;Pooling=true;Max Pool Size=10") | ||||
| 	//	.UseLogger(new LoggerFactory().CreateLogger("FreeSql.SqlServer")) | ||||
| 	//	.UseAutoSyncStructure(false) | ||||
| 	//	.Build(); | ||||
|  | ||||
| 	//public static IFreeSql pgsql = new FreeSql.FreeSqlBuilder() | ||||
| 	//	.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=10") | ||||
| 	//	.UseLogger(new LoggerFactory().CreateLogger("FreeSql.PostgreSQL")) | ||||
| 	//	.UseAutoSyncStructure(false) | ||||
| 	//	.UseSyncStructureToLower(true) | ||||
| 	//	.Build(); | ||||
|  | ||||
| 	//public static IFreeSql oracle = new FreeSql.FreeSqlBuilder() | ||||
| 	//	.UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=10") | ||||
| 	//	.UseLogger(new LoggerFactory().CreateLogger("FreeSql.Oracle")) | ||||
| 	//	.UseAutoSyncStructure(false) | ||||
| 	//	.Build(); | ||||
|  | ||||
| 	//public static IFreeSql sqlite = new FreeSql.FreeSqlBuilder() | ||||
| 	//	.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10") | ||||
| 	//	.UseLogger(new LoggerFactory().CreateLogger("FreeSql.Sqlite")) | ||||
| 	//	.UseAutoSyncStructure(false) | ||||
| 	//	.Build(); | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,6 @@ | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="FreeSql.DbContext" Version="0.5.19" /> | ||||
| 		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.8" /> | ||||
| 		<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> | ||||
| 		<PackageReference Include="xunit" Version="2.4.0" /> | ||||
| @@ -15,7 +14,14 @@ | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext\FreeSql.DbContext.csproj" /> | ||||
| 		<ProjectReference Include="..\Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj" /> | ||||
| 		<ProjectReference Include="..\FreeSql\FreeSql.csproj" /> | ||||
| 		<ProjectReference Include="..\Providers\FreeSql.Provider.MySql\FreeSql.Provider.MySql.csproj" /> | ||||
| 		<ProjectReference Include="..\Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj" /> | ||||
| 		<ProjectReference Include="..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" /> | ||||
| 		<ProjectReference Include="..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" /> | ||||
| 		<ProjectReference Include="..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
|   | ||||
| @@ -1,27 +0,0 @@ | ||||
| using FreeSql.DataAnnotations; | ||||
| using FreeSql.Generator; | ||||
| using System; | ||||
| using Xunit; | ||||
|  | ||||
| namespace FreeSql.Tests.Generator { | ||||
| 	public class MySqlTemplateGeneratorTest { | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildSimpleEntity() { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(g.mysql.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\MySql\simple-entity", @"C:\Users\28810\Desktop\新建文件夹 (9)", "cccddd"); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildSimpleEntityNavigationObject () { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(g.mysql.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\MySql\simple-entity-navigation-object", @"C:\Users\28810\Desktop\新建文件夹 (9)", "cccddd"); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildRichEntityNavigationObject() { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(g.mysql.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\MySql\rich-entity-navigation-object", @"C:\Users\28810\Desktop\新建文件夹 (9)", "cccddd"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,27 +0,0 @@ | ||||
| using FreeSql.DataAnnotations; | ||||
| using FreeSql.Generator; | ||||
| using System; | ||||
| using Xunit; | ||||
|  | ||||
| namespace FreeSql.Tests.Generator { | ||||
| 	public class PostgreSQLTemplateGeneratorTest { | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildSimpleEntity() { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(g.pgsql.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\PostgreSQL\simple-entity", @"C:\Users\28810\Desktop\新建文件夹 (9)", "tedb"); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildSimpleEntityNavigationObject () { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(g.pgsql.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\PostgreSQL\simple-entity-navigation-object", @"C:\Users\28810\Desktop\新建文件夹 (9)", "tedb"); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildRichEntityNavigationObject() { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(g.pgsql.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\PostgreSQL\rich-entity-navigation-object", @"C:\Users\28810\Desktop\新建文件夹 (9)", "tedb"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,37 +0,0 @@ | ||||
| using FreeSql.DataAnnotations; | ||||
| using FreeSql.Generator; | ||||
| using FreeSql.Tests.DataContext.SqlServer; | ||||
| using System; | ||||
| using Xunit; | ||||
|  | ||||
| namespace FreeSql.Tests.Generator { | ||||
|  | ||||
| 	[Collection("SqlServerCollection")] | ||||
| 	public class SqlServerTemplateGeneratorTest { | ||||
| 		SqlServerFixture _sqlserverFixture; | ||||
|  | ||||
| 		public SqlServerTemplateGeneratorTest(SqlServerFixture sqlserverFixture) | ||||
| 		{ | ||||
| 			_sqlserverFixture = sqlserverFixture; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildSimpleEntity() { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(_sqlserverFixture.SqlServer.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\SqlServer\simple-entity", @"C:\Users\28810\Desktop\新建文件夹 (9)", "shop"); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildSimpleEntityNavigationObject () { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(_sqlserverFixture.SqlServer.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\SqlServer\simple-entity-navigation-object", @"C:\Users\28810\Desktop\新建文件夹 (9)", "shop"); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void BuildRichEntityNavigationObject() { | ||||
| 			var gen = new TemplateGenerator(); | ||||
| 			gen.Build(_sqlserverFixture.SqlServer.DbFirst, @"C:\Users\28810\Desktop\github\FreeSql\Templates\SqlServer\rich-entity-navigation-object", @"C:\Users\28810\Desktop\新建文件夹 (9)", "shop"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -230,8 +230,8 @@ namespace FreeSql.Tests.MySql { | ||||
|  | ||||
| 			}); | ||||
|  | ||||
| 			var t100 = g.mysql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).Caching(50).ToList(); | ||||
| 			var t101 = g.mysql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).Caching(50).ToList(); | ||||
| 			var t100 = g.mysql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToList(); | ||||
| 			var t101 = g.mysql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToList(); | ||||
|  | ||||
|  | ||||
| 			var t1111 = g.mysql.Select<TestInfo>().ToList(a => new { a.Id, a.Title, a.Type }); | ||||
| @@ -304,16 +304,6 @@ namespace FreeSql.Tests.MySql { | ||||
| 			Assert.StartsWith(" SELECT", select.Master().Where(a => 1 == 1).ToSql()); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void Caching() { | ||||
| 			var result1 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching1 = g.mysql.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching1); | ||||
| 			var result2 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching2 = g.mysql.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching2); | ||||
| 			Assert.Equal(result1.Count, result1.Count); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void From() { | ||||
| 			var query2 = select.From<TestTypeInfo>((s, b) => s | ||||
| 				 .LeftJoin(a => a.TypeGuid == b.Guid) | ||||
|   | ||||
| @@ -385,27 +385,11 @@ namespace FreeSql.Tests.MySql { | ||||
| 			internal static IFreeSql mysql => null; | ||||
| 			public static FreeSql.ISelect<Tb_alltype> Select => mysql.Select<Tb_alltype>(); | ||||
|  | ||||
| 			public static int ItemCacheTimeout = 180; | ||||
| 			public static Tb_alltype GetItem(int Id) => Select.Where(a => a.Id == Id).Caching(ItemCacheTimeout, string.Concat("test:tb_alltype:", Id)).ToOne(); | ||||
|  | ||||
| 			public static long Delete(int Id) { | ||||
| 				var affrows = mysql.Delete<Tb_alltype>().Where(a => a.Id == Id).ExecuteAffrows(); | ||||
| 				if (ItemCacheTimeout > 0) RemoveCache(new Tb_alltype { Id = Id }); | ||||
| 				return affrows; | ||||
| 			} | ||||
|  | ||||
| 			internal static void RemoveCache(Tb_alltype item) => RemoveCache(item == null ? null : new[] { item }); | ||||
| 			internal static void RemoveCache(IEnumerable<Tb_alltype> items) { | ||||
| 				if (ItemCacheTimeout <= 0 || items == null || items.Any() == false) return; | ||||
| 				var keys = new string[items.Count() * 1]; | ||||
| 				var keysIdx = 0; | ||||
| 				foreach (var item in items) { | ||||
| 					keys[keysIdx++] = string.Concat("test:tb_alltype:", item.Id); | ||||
| 				} | ||||
| 				if (mysql.Ado.TransactionCurrentThread != null) mysql.Ado.TransactionPreRemoveCache(keys); | ||||
| 				else mysql.Cache.Remove(keys); | ||||
| 			} | ||||
|  | ||||
| 			/// <summary> | ||||
| 			/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Update<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 0 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Insert | ||||
| 			/// </summary> | ||||
|   | ||||
| @@ -199,16 +199,6 @@ namespace FreeSql.Tests.Oracle { | ||||
| 			Assert.StartsWith(" SELECT", select.Master().Where(a => 1 == 1).ToSql()); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void Caching() { | ||||
| 			var result1 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching1 = g.oracle.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching1); | ||||
| 			var result2 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching2 = g.oracle.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching2); | ||||
| 			Assert.Equal(result1.Count, result1.Count); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void From() { | ||||
| 			var query2 = select.From<TestTypeInfo>((s, b) => s | ||||
| 				 .LeftJoin(a => a.TypeGuid == b.Guid) | ||||
|   | ||||
| @@ -208,8 +208,8 @@ namespace FreeSql.Tests.PostgreSQL { | ||||
|  | ||||
| 			}); | ||||
|  | ||||
| 			var t100 = g.pgsql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).Caching(50).ToList(); | ||||
| 			var t101 = g.pgsql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).Caching(50).ToList(); | ||||
| 			var t100 = g.pgsql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToList(); | ||||
| 			var t101 = g.pgsql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToList(); | ||||
|  | ||||
|  | ||||
| 			var t1111 = g.pgsql.Select<TestInfo>().ToList(a => new { a.Id, a.Title, a.Type }); | ||||
| @@ -268,16 +268,7 @@ namespace FreeSql.Tests.PostgreSQL { | ||||
| 		public void Master() { | ||||
| 			Assert.StartsWith(" SELECT", select.Master().Where(a => 1 == 1).ToSql()); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void Caching() { | ||||
| 			var result1 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching1 = g.pgsql.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching1); | ||||
| 			var result2 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching2 = g.pgsql.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching2); | ||||
| 			Assert.Equal(result1.Count, result1.Count); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void From() { | ||||
|  | ||||
|   | ||||
| @@ -200,16 +200,7 @@ namespace FreeSql.Tests.SqlServer { | ||||
| 		public void Master() { | ||||
| 			Assert.StartsWith(" SELECT", select.Master().Where(a => 1 == 1).ToSql()); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void Caching() { | ||||
| 			var result1 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching1 = _sqlserverFixture.SqlServer.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching1); | ||||
| 			var result2 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching2 = _sqlserverFixture.SqlServer.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching2); | ||||
| 			Assert.Equal(result1.Count, result1.Count); | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void From() { | ||||
| 			var query2 = select.From<TestTypeInfo>((s, b) => s | ||||
|   | ||||
| @@ -210,16 +210,6 @@ namespace FreeSql.Tests.Sqlite { | ||||
| 			Assert.StartsWith(" SELECT", select.Master().Where(a => 1 == 1).ToSql()); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void Caching() { | ||||
| 			var result1 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching1 = g.sqlite.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching1); | ||||
| 			var result2 = select.Where(a => 1 == 1).Caching(20, "testcaching").ToList(); | ||||
| 			var testcaching2 = g.sqlite.Cache.Get("testcaching"); | ||||
| 			Assert.NotNull(testcaching2); | ||||
| 			Assert.Equal(result1.Count, result1.Count); | ||||
| 		} | ||||
| 		[Fact] | ||||
| 		public void From() { | ||||
| 			var query2 = select.From<TestTypeInfo>((s, b) => s | ||||
| 				 .LeftJoin(a => a.TypeGuid == b.Guid) | ||||
|   | ||||
| @@ -508,8 +508,8 @@ namespace FreeSql.Tests { | ||||
|  | ||||
| 			}); | ||||
|  | ||||
| 			var t100 = g.mysql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).Caching(50).ToList(); | ||||
| 			var t101 = g.mysql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).Caching(50).ToList(); | ||||
| 			var t100 = g.mysql.Select<TestInfo>().Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToList(); | ||||
| 			var t101 = g.mysql.Select<TestInfo>().As("b").Where("").Where(a => a.Id > 0).Skip(100).Limit(200).ToList(); | ||||
|  | ||||
|  | ||||
| 			var t1111 = g.mysql.Select<TestInfo>().ToList(a => new { a.Id, a.Title, a.Type }); | ||||
|   | ||||
							
								
								
									
										122
									
								
								FreeSql.sln
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								FreeSql.sln
									
									
									
									
									
								
							| @@ -24,6 +24,26 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "orm_vs", "Examples\orm_vs\o | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "benchmarker", "Examples\benchmarker\benchmarker.csproj", "{E7405816-F32A-4F3E-AD76-29129962C6AA}" | ||||
| EndProject | ||||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Providers", "Providers", "{2A381C57-2697-427B-9F10-55DA11FD02E4}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.MySql", "Providers\FreeSql.Provider.MySql\FreeSql.Provider.MySql.csproj", "{28C6A39C-7AE7-4210-B7B0-0970216637A8}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.Oracle", "Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj", "{3DE45286-B0DB-4D74-B322-F5467FB2EF53}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Provider.Sqlite", "Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj", "{559B6369-1868-4A06-A590-F80BA7B80A1B}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Provider.SqlServer", "Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj", "{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Provider.PostgreSQL", "Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj", "{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}" | ||||
| EndProject | ||||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Extensions.LazyLoading", "Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj", "{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.DbContext", "..\FreeSql.DbContext\FreeSql.DbContext\FreeSql.DbContext.csproj", "{84BA8C1A-A432-4D03-A2FA-127B8776C872}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Repository", "..\FreeSql.DbContext\FreeSql.Repository\FreeSql.Repository.csproj", "{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| @@ -118,6 +138,102 @@ Global | ||||
| 		{E7405816-F32A-4F3E-AD76-29129962C6AA}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{E7405816-F32A-4F3E-AD76-29129962C6AA}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{E7405816-F32A-4F3E-AD76-29129962C6AA}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{84BA8C1A-A432-4D03-A2FA-127B8776C872}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{8B92F97B-02FC-4FA0-8FA5-F494CAF15336}.Release|x86.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| @@ -127,6 +243,12 @@ Global | ||||
| 		{B93981B8-3295-4EDD-B314-BCA77B6BF37A} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B} | ||||
| 		{1A5EC2EB-8C2B-4547-8AC6-EB5C0DE0CA81} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B} | ||||
| 		{E7405816-F32A-4F3E-AD76-29129962C6AA} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B} | ||||
| 		{28C6A39C-7AE7-4210-B7B0-0970216637A8} = {2A381C57-2697-427B-9F10-55DA11FD02E4} | ||||
| 		{3DE45286-B0DB-4D74-B322-F5467FB2EF53} = {2A381C57-2697-427B-9F10-55DA11FD02E4} | ||||
| 		{559B6369-1868-4A06-A590-F80BA7B80A1B} = {2A381C57-2697-427B-9F10-55DA11FD02E4} | ||||
| 		{B61AAC9E-59E9-4F47-BBE3-97AC24112EFE} = {2A381C57-2697-427B-9F10-55DA11FD02E4} | ||||
| 		{22C0B061-F7CC-4A7F-AEC7-D4DBBE6B23B2} = {2A381C57-2697-427B-9F10-55DA11FD02E4} | ||||
| 		{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA} | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||
| 		SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98} | ||||
|   | ||||
| @@ -66,7 +66,7 @@ namespace FreeSql.DataAnnotations { | ||||
| 		/// <summary> | ||||
| 		/// 数据库默认值 | ||||
| 		/// </summary> | ||||
| 		internal object DbDefautValue { get; set; } | ||||
| 		public object DbDefautValue { get; set; } | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 类型映射,比如:可将 enum 属性映射成 typeof(string) | ||||
|   | ||||
| @@ -5,46 +5,46 @@ namespace FreeSql.DatabaseModel { | ||||
| 		/// <summary> | ||||
| 		/// 所属表 | ||||
| 		/// </summary> | ||||
| 		public DbTableInfo Table { get; internal set; } | ||||
| 		public DbTableInfo Table { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 列名 | ||||
| 		/// </summary> | ||||
| 		public string Name { get; internal set; } | ||||
| 		public string Name { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 映射到 C# 类型 | ||||
| 		/// </summary> | ||||
| 		public Type CsType { get; internal set; } | ||||
| 		public Type CsType { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 数据库枚举类型int值 | ||||
| 		/// </summary> | ||||
| 		public int DbType { get; internal set; } | ||||
| 		public int DbType { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 数据库类型,字符串,varchar | ||||
| 		/// </summary> | ||||
| 		public string DbTypeText { get; internal set; } | ||||
| 		public string DbTypeText { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 数据库类型,字符串,varchar(255) | ||||
| 		/// </summary> | ||||
| 		public string DbTypeTextFull { get; internal set; } | ||||
| 		public string DbTypeTextFull { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 最大长度 | ||||
| 		/// </summary> | ||||
| 		public int MaxLength { get; internal set; } | ||||
| 		public int MaxLength { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 主键 | ||||
| 		/// </summary> | ||||
| 		public bool IsPrimary { get; internal set; } | ||||
| 		public bool IsPrimary { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 自增标识 | ||||
| 		/// </summary> | ||||
| 		public bool IsIdentity { get; internal set; } | ||||
| 		public bool IsIdentity { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 是否可DBNull | ||||
| 		/// </summary> | ||||
| 		public bool IsNullable { get; internal set; } | ||||
| 		public bool IsNullable { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 备注 | ||||
| 		/// </summary> | ||||
| 		public string Coment { get; internal set; } | ||||
| 		public string Coment { get; set; } | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -6,19 +6,19 @@ namespace FreeSql.DatabaseModel { | ||||
| 		/// <summary> | ||||
| 		/// 唯一标识 | ||||
| 		/// </summary> | ||||
| 		public string Id { get; internal set; } | ||||
| 		public string Id { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// SqlServer下是Owner、PostgreSQL下是Schema、MySql下是数据库名 | ||||
| 		/// </summary> | ||||
| 		public string Schema { get; internal set; } | ||||
| 		public string Schema { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 表名 | ||||
| 		/// </summary> | ||||
| 		public string Name { get; internal set; } | ||||
| 		public string Name { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 表备注,SqlServer下是扩展属性 MS_Description | ||||
| 		/// </summary> | ||||
| 		public string Comment { get; internal set; } | ||||
| 		public string Comment { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 表/视图 | ||||
| 		/// </summary> | ||||
| @@ -26,27 +26,27 @@ namespace FreeSql.DatabaseModel { | ||||
| 		/// <summary> | ||||
| 		/// 列 | ||||
| 		/// </summary> | ||||
| 		public List<DbColumnInfo> Columns { get; internal set; } = new List<DbColumnInfo>(); | ||||
| 		public List<DbColumnInfo> Columns { get; set; } = new List<DbColumnInfo>(); | ||||
| 		/// <summary> | ||||
| 		/// 自增列 | ||||
| 		/// </summary> | ||||
| 		public List<DbColumnInfo> Identitys { get; internal set; } = new List<DbColumnInfo>(); | ||||
| 		public List<DbColumnInfo> Identitys { get; set; } = new List<DbColumnInfo>(); | ||||
| 		/// <summary> | ||||
| 		/// 主键/组合 | ||||
| 		/// </summary> | ||||
| 		public List<DbColumnInfo> Primarys { get; internal set; } = new List<DbColumnInfo>(); | ||||
| 		public List<DbColumnInfo> Primarys { get; set; } = new List<DbColumnInfo>(); | ||||
| 		/// <summary> | ||||
| 		/// 唯一键/组合 | ||||
| 		/// </summary> | ||||
| 		public Dictionary<string, List<DbColumnInfo>> UniquesDict { get; internal set; } = new Dictionary<string, List<DbColumnInfo>>(); | ||||
| 		public Dictionary<string, List<DbColumnInfo>> UniquesDict { get; set; } = new Dictionary<string, List<DbColumnInfo>>(); | ||||
| 		/// <summary> | ||||
| 		/// 索引/组合 | ||||
| 		/// </summary> | ||||
| 		public Dictionary<string, List<DbColumnInfo>> IndexesDict { get; internal set; } = new Dictionary<string, List<DbColumnInfo>>(); | ||||
| 		public Dictionary<string, List<DbColumnInfo>> IndexesDict { get; set; } = new Dictionary<string, List<DbColumnInfo>>(); | ||||
| 		/// <summary> | ||||
| 		/// 外键 | ||||
| 		/// </summary> | ||||
| 		public Dictionary<string, DbForeignInfo> ForeignsDict { get; internal set; } = new Dictionary<string, DbForeignInfo>(); | ||||
| 		public Dictionary<string, DbForeignInfo> ForeignsDict { get; set; } = new Dictionary<string, DbForeignInfo>(); | ||||
|  | ||||
| 		public List<List<DbColumnInfo>> Uniques => UniquesDict.Values.ToList(); | ||||
| 		public List<List<DbColumnInfo>> Indexes => IndexesDict.Values.ToList(); | ||||
|   | ||||
| @@ -2,10 +2,10 @@ | ||||
|  | ||||
| namespace FreeSql.DatabaseModel { | ||||
| 	public class DbForeignInfo { | ||||
| 		public DbTableInfo Table { get; internal set; } | ||||
| 		public List<DbColumnInfo> Columns { get; internal set; } = new List<DbColumnInfo>(); | ||||
| 		public DbTableInfo ReferencedTable { get; internal set; } | ||||
| 		public List<DbColumnInfo> ReferencedColumns { get; internal set; } = new List<DbColumnInfo>(); | ||||
| 		public DbTableInfo Table { get; set; } | ||||
| 		public List<DbColumnInfo> Columns { get; set; } = new List<DbColumnInfo>(); | ||||
| 		public DbTableInfo ReferencedTable { get; set; } | ||||
| 		public List<DbColumnInfo> ReferencedColumns { get; set; } = new List<DbColumnInfo>(); | ||||
|  | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,7 @@ public static partial class FreeSqlGlobalExtensions { | ||||
| 	public static bool IsNumberType(this Type that) => that == null ? false : dicIsNumberType.Value.ContainsKey(that); | ||||
| 	public static bool IsNullableType(this Type that) => that?.FullName.StartsWith("System.Nullable`1[") == true; | ||||
| 	public static bool IsAnonymousType(this Type that) => that?.FullName.StartsWith("<>f__AnonymousType") == true; | ||||
| 	internal static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GenericTypeArguments.First() : that; | ||||
| 	public static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GenericTypeArguments.First() : that; | ||||
|  | ||||
| 	/// <summary> | ||||
| 	/// 测量两个经纬度的距离,返回单位:米 | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<Version>0.5.23</Version> | ||||
| 		<Version>0.6.1</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite.</Description> | ||||
| @@ -23,18 +23,7 @@ | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="CS-Script.Core" Version="1.0.6" /> | ||||
| 		<PackageReference Include="Microsoft.CSharp" Version="4.5.0" /> | ||||
| 		<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.1.0" /> | ||||
| 		<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" /> | ||||
| 		<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.0" /> | ||||
| 		<PackageReference Include="MySql.Data" Version="8.0.15" /> | ||||
| 		<PackageReference Include="Newtonsoft.Json" Version="12.0.1" /> | ||||
| 		<PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.5" /> | ||||
| 		<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.18.5" /> | ||||
| 		<PackageReference Include="SafeObjectPool" Version="2.0.1" /> | ||||
| 		<PackageReference Include="System.Data.SqlClient" Version="4.6.0" /> | ||||
| 		<PackageReference Include="System.Data.SQLite.Core" Version="1.0.110" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| @@ -409,20 +409,6 @@ | ||||
|             <param name="columnType"></param> | ||||
|             <param name="setExp"></param> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.FreeSqlBuilder.UseCache(Microsoft.Extensions.Caching.Distributed.IDistributedCache)"> | ||||
|             <summary> | ||||
|             使用缓存,不指定默认使用内存 | ||||
|             </summary> | ||||
|             <param name="cache">缓存实现</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.FreeSqlBuilder.UseLogger(Microsoft.Extensions.Logging.ILogger)"> | ||||
|             <summary> | ||||
|             使用日志,不指定默认输出控制台 | ||||
|             </summary> | ||||
|             <param name="logger"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.FreeSqlBuilder.UseConnectionString(FreeSql.DataType,System.String)"> | ||||
|             <summary> | ||||
|             使用连接串 | ||||
| @@ -488,16 +474,6 @@ | ||||
|             <param name="executed">执行后,可监视执行性能</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.Generator.TemplateEngin.ITemplateOutput.OuTpUt(System.Text.StringBuilder,System.Collections.IDictionary,System.String,FreeSql.Generator.TemplateEngin)"> | ||||
|             <summary> | ||||
|              | ||||
|             </summary> | ||||
|             <param name="tOuTpUt">返回内容</param> | ||||
|             <param name="oPtIoNs">渲染对象</param> | ||||
|             <param name="rEfErErFiLeNaMe">当前文件路径</param> | ||||
|             <param name="tEmPlAtEsEnDeR"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.IDelete`1.WithTransaction(System.Data.Common.DbTransaction)"> | ||||
|             <summary> | ||||
|             指定事务对象 | ||||
| @@ -807,14 +783,6 @@ | ||||
|             </summary> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ISelect0`2.Caching(System.Int32,System.String)"> | ||||
|             <summary> | ||||
|             缓存查询结果 | ||||
|             </summary> | ||||
|             <param name="seconds">缓存秒数</param> | ||||
|             <param name="key">缓存key</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ISelect0`2.LeftJoin(System.Linq.Expressions.Expression{System.Func{`1,System.Boolean}})"> | ||||
|             <summary> | ||||
|             左联查询,使用导航属性自动生成SQL | ||||
| @@ -1643,12 +1611,6 @@ | ||||
|             当前线程的事务 | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.IAdo.TransactionPreRemoveCache(System.String[])"> | ||||
|             <summary> | ||||
|             事务完成前预删除缓存 | ||||
|             </summary> | ||||
|             <param name="keys"></param> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.IAdo.ExecuteReader(System.Action{System.Data.Common.DbDataReader},System.Data.CommandType,System.String,System.Data.Common.DbParameter[])"> | ||||
|             <summary> | ||||
|             查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】 | ||||
| @@ -2081,118 +2043,6 @@ | ||||
|             耗时(单位:毫秒) | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="P:FreeSql.ICache.Serialize"> | ||||
|             <summary> | ||||
|             缓存数据时序列化方法,若无设置则默认使用 Json.net | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="P:FreeSql.ICache.Deserialize"> | ||||
|             <summary> | ||||
|             获取缓存数据时反序列化方法,若无设置则默认使用 Json.net | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.Set``1(System.String,``0,System.Int32)"> | ||||
|             <summary> | ||||
|             缓存可序列化数据 | ||||
|             </summary> | ||||
|             <typeparam name="T"></typeparam> | ||||
|             <param name="key">缓存键</param> | ||||
|             <param name="data">可序列化数据</param> | ||||
|             <param name="timeoutSeconds">缓存秒数,<=0时永久缓存</param> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.Get``1(System.String)"> | ||||
|             <summary> | ||||
|             循环或批量获取缓存数据 | ||||
|             </summary> | ||||
|             <typeparam name="T"></typeparam> | ||||
|             <param name="key"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.Get(System.String)"> | ||||
|             <summary> | ||||
|             循环或批量获取缓存数据 | ||||
|             </summary> | ||||
|             <param name="key"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.Remove(System.String[])"> | ||||
|             <summary> | ||||
|             循环或批量删除缓存键 | ||||
|             </summary> | ||||
|             <param name="keys">缓存键[数组]</param> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.Shell``1(System.String,System.Int32,System.Func{``0})"> | ||||
|             <summary> | ||||
|             缓存壳 | ||||
|             </summary> | ||||
|             <typeparam name="T">缓存类型</typeparam> | ||||
|             <param name="key">缓存键</param> | ||||
|             <param name="timeoutSeconds">缓存秒数</param> | ||||
|             <param name="getData">获取源数据的函数</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.Shell``1(System.String,System.String,System.Int32,System.Func{``0})"> | ||||
|             <summary> | ||||
|             缓存壳(哈希表) | ||||
|             </summary> | ||||
|             <typeparam name="T">缓存类型</typeparam> | ||||
|             <param name="key">缓存键</param> | ||||
|             <param name="field">字段</param> | ||||
|             <param name="timeoutSeconds">缓存秒数</param> | ||||
|             <param name="getData">获取源数据的函数</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.SetAsync``1(System.String,``0,System.Int32)"> | ||||
|             <summary> | ||||
|             缓存可序列化数据 | ||||
|             </summary> | ||||
|             <typeparam name="T"></typeparam> | ||||
|             <param name="key">缓存键</param> | ||||
|             <param name="data">可序列化数据</param> | ||||
|             <param name="timeoutSeconds">缓存秒数,<=0时永久缓存</param> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.GetAsync``1(System.String)"> | ||||
|             <summary> | ||||
|             循环或批量获取缓存数据 | ||||
|             </summary> | ||||
|             <typeparam name="T"></typeparam> | ||||
|             <param name="key"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.GetAsync(System.String)"> | ||||
|             <summary> | ||||
|             循环或批量获取缓存数据 | ||||
|             </summary> | ||||
|             <param name="key"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.RemoveAsync(System.String[])"> | ||||
|             <summary> | ||||
|             循环或批量删除缓存键 | ||||
|             </summary> | ||||
|             <param name="keys">缓存键[数组]</param> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.ShellAsync``1(System.String,System.Int32,System.Func{System.Threading.Tasks.Task{``0}})"> | ||||
|             <summary> | ||||
|             缓存壳 | ||||
|             </summary> | ||||
|             <typeparam name="T">缓存类型</typeparam> | ||||
|             <param name="key">缓存键</param> | ||||
|             <param name="timeoutSeconds">缓存秒数</param> | ||||
|             <param name="getDataAsync">获取源数据的函数</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.ICache.ShellAsync``1(System.String,System.String,System.Int32,System.Func{System.Threading.Tasks.Task{``0}})"> | ||||
|             <summary> | ||||
|             缓存壳(哈希表) | ||||
|             </summary> | ||||
|             <typeparam name="T">缓存类型</typeparam> | ||||
|             <param name="key">缓存键</param> | ||||
|             <param name="field">字段</param> | ||||
|             <param name="timeoutSeconds">缓存秒数</param> | ||||
|             <param name="getDataAsync">获取源数据的函数</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="P:FreeSql.ICodeFirst.IsAutoSyncStructure"> | ||||
|             <summary> | ||||
|             【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改 | ||||
| @@ -2385,46 +2235,6 @@ | ||||
|             <param name="that"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSqlGlobalExtensions.FormatMySql(System.String,System.Object[])"> | ||||
|             <summary> | ||||
|             特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 | ||||
|             </summary> | ||||
|             <param name="that"></param> | ||||
|             <param name="args"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSqlGlobalExtensions.FormatOracleSQL(System.String,System.Object[])"> | ||||
|             <summary> | ||||
|             特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 | ||||
|             </summary> | ||||
|             <param name="that"></param> | ||||
|             <param name="args"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSqlGlobalExtensions.FormatPostgreSQL(System.String,System.Object[])"> | ||||
|             <summary> | ||||
|             特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 | ||||
|             </summary> | ||||
|             <param name="that"></param> | ||||
|             <param name="args"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSqlGlobalExtensions.FormatSqlite(System.String,System.Object[])"> | ||||
|             <summary> | ||||
|             特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 | ||||
|             </summary> | ||||
|             <param name="that"></param> | ||||
|             <param name="args"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeSqlGlobalExtensions.FormatSqlServer(System.String,System.Object[])"> | ||||
|             <summary> | ||||
|             特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 | ||||
|             </summary> | ||||
|             <param name="that"></param> | ||||
|             <param name="args"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="M:FreeUtil.NewMongodbId"> | ||||
|             <summary> | ||||
|             生成类似Mongodb的ObjectId有序、不重复Guid | ||||
| @@ -2520,11 +2330,6 @@ | ||||
|             <param name="handler">事务体 () => {}</param> | ||||
|             <param name="timeout">超时,未执行完将自动提交</param> | ||||
|         </member> | ||||
|         <member name="P:IFreeSql.Cache"> | ||||
|             <summary> | ||||
|             缓存 | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="P:IFreeSql.Ado"> | ||||
|             <summary> | ||||
|             数据库访问对象 | ||||
| @@ -2545,36 +2350,5 @@ | ||||
|             DbFirst 模式开发相关方法 | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="M:MygisTypesExtensions.Distance(MygisPoint,MygisPoint)"> | ||||
|             <summary> | ||||
|             测量两个经纬度的距离,返回单位:米 | ||||
|             </summary> | ||||
|             <param name="that">经纬坐标1</param> | ||||
|             <param name="point">经纬坐标2</param> | ||||
|             <returns>返回距离(单位:米)</returns> | ||||
|         </member> | ||||
|         <member name="M:PostgreSQLTypesExtensions.Distance(NpgsqlTypes.NpgsqlPoint,NpgsqlTypes.NpgsqlPoint)"> | ||||
|             <summary> | ||||
|             测量两个经纬度的距离,返回单位:米 | ||||
|             </summary> | ||||
|             <param name="that">经纬坐标1</param> | ||||
|             <param name="point">经纬坐标2</param> | ||||
|             <returns>返回距离(单位:米)</returns> | ||||
|         </member> | ||||
|         <member name="M:PostgreSQLTypesExtensions.Distance(Npgsql.LegacyPostgis.PostgisPoint,Npgsql.LegacyPostgis.PostgisPoint)"> | ||||
|             <summary> | ||||
|             测量两个经纬度的距离,返回单位:米 | ||||
|             </summary> | ||||
|             <param name="that">经纬坐标1</param> | ||||
|             <param name="point">经纬坐标2</param> | ||||
|             <returns>返回距离(单位:米)</returns> | ||||
|         </member> | ||||
|         <member name="M:PostgreSQLTypesExtensions.ToBitArray(System.String)"> | ||||
|             <summary> | ||||
|             将 1010101010 这样的二进制字符串转换成 BitArray | ||||
|             </summary> | ||||
|             <param name="_1010Str">1010101010</param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|     </members> | ||||
| </doc> | ||||
|   | ||||
| @@ -1,12 +1,8 @@ | ||||
| using Microsoft.Extensions.Caching.Distributed; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System; | ||||
| using System.Data.Common; | ||||
|  | ||||
| namespace FreeSql { | ||||
| 	public class FreeSqlBuilder { | ||||
| 		IDistributedCache _cache; | ||||
| 		ILogger _logger; | ||||
| 		DataType _dataType; | ||||
| 		string _masterConnectionString; | ||||
| 		string[] _slaveConnectionString; | ||||
| @@ -19,25 +15,6 @@ namespace FreeSql { | ||||
| 		Action<DbCommand> _aopCommandExecuting = null; | ||||
| 		Action<DbCommand, string> _aopCommandExecuted = null; | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 使用缓存,不指定默认使用内存 | ||||
| 		/// </summary> | ||||
| 		/// <param name="cache">缓存实现</param> | ||||
| 		/// <returns></returns> | ||||
| 		public FreeSqlBuilder UseCache(IDistributedCache cache) { | ||||
| 			_cache = cache; | ||||
| 			return this; | ||||
| 		} | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 使用日志,不指定默认输出控制台 | ||||
| 		/// </summary> | ||||
| 		/// <param name="logger"></param> | ||||
| 		/// <returns></returns> | ||||
| 		public FreeSqlBuilder UseLogger(ILogger logger) { | ||||
| 			_logger = logger; | ||||
| 			return this; | ||||
| 		} | ||||
| 		/// <summary> | ||||
| 		/// 使用连接串 | ||||
| 		/// </summary> | ||||
| @@ -127,14 +104,27 @@ namespace FreeSql { | ||||
| 		public IFreeSql Build() => Build<IFreeSql>(); | ||||
| 		public IFreeSql<TMark> Build<TMark>() { | ||||
| 			IFreeSql<TMark> ret = null; | ||||
| 			Type type = null; | ||||
| 			switch(_dataType) { | ||||
| 				case DataType.MySql: ret = new MySql.MySqlProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; | ||||
| 				case DataType.SqlServer: ret = new SqlServer.SqlServerProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; | ||||
| 				case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; | ||||
| 				case DataType.Oracle: ret = new Oracle.OracleProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; | ||||
| 				case DataType.Sqlite: ret = new Sqlite.SqliteProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break; | ||||
| 				case DataType.MySql: | ||||
| 					type = Type.GetType("FreeSql.MySql.MySqlProvider`1,FreeSql.Provider.MySql")?.MakeGenericType(typeof(TMark)); | ||||
| 					if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载"); | ||||
| 					break; | ||||
| 				case DataType.SqlServer: type = Type.GetType("FreeSql.SqlServer.SqlServerProvider`1,FreeSql.Provider.SqlServer")?.MakeGenericType(typeof(TMark)); | ||||
| 					if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.SqlServer.dll,可前往 nuget 下载"); | ||||
| 					break; | ||||
| 				case DataType.PostgreSQL: type = Type.GetType("FreeSql.PostgreSQL.PostgreSQLProvider`1,FreeSql.Provider.PostgreSQL")?.MakeGenericType(typeof(TMark)); | ||||
| 					if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.PostgreSQL.dll,可前往 nuget 下载"); | ||||
| 					break; | ||||
| 				case DataType.Oracle: type = Type.GetType("FreeSql.Oracle.OracleProvider`1,FreeSql.Provider.Oracle")?.MakeGenericType(typeof(TMark)); | ||||
| 					if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.Oracle.dll,可前往 nuget 下载"); | ||||
| 					break; | ||||
| 				case DataType.Sqlite: type = Type.GetType("FreeSql.Sqlite.SqliteProvider`1,FreeSql.Provider.Sqlite")?.MakeGenericType(typeof(TMark)); | ||||
| 					if (type == null) throw new Exception("缺少 FreeSql 数据库实现包:FreeSql.Provider.Sqlite.dll,可前往 nuget 下载"); | ||||
| 					break; | ||||
| 				default: throw new Exception("未指定 UseConnectionString"); | ||||
| 			} | ||||
| 			ret = Activator.CreateInstance(type, new object[] { _masterConnectionString, _slaveConnectionString }) as IFreeSql<TMark>; | ||||
| 			if (ret != null) { | ||||
| 				ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure; | ||||
| 				 | ||||
|   | ||||
| @@ -31,38 +31,4 @@ public static class FreeUtil { | ||||
| 		var guid = $"{uninxtime.ToString("x8").PadLeft(8, '0')}{__staticMachine.ToString("x8").PadLeft(8, '0').Substring(2, 6)}{__staticPid.ToString("x8").PadLeft(8, '0').Substring(6, 2)}{increment.ToString("x8").PadLeft(8, '0')}{rand.ToString("x8").PadLeft(8, '0')}"; | ||||
| 		return Guid.Parse(guid); | ||||
| 	} | ||||
|  | ||||
| 	internal static void PrevReheatConnectionPool(ObjectPool<DbConnection> pool, int minPoolSize) { | ||||
| 		if (minPoolSize <= 0) minPoolSize = Math.Min(5, pool.Policy.PoolSize); | ||||
| 		if (minPoolSize > pool.Policy.PoolSize) minPoolSize = pool.Policy.PoolSize; | ||||
| 		var initTestOk = true; | ||||
| 		var initStartTime = DateTime.Now; | ||||
| 		var initConns = new ConcurrentBag<Object<DbConnection>>(); | ||||
|  | ||||
| 		try { | ||||
| 			var conn = pool.Get(); | ||||
| 			initConns.Add(conn); | ||||
| 			pool.Policy.OnCheckAvailable(conn); | ||||
| 		} catch { | ||||
| 			initTestOk = false; //预热一次失败,后面将不进行 | ||||
| 		} | ||||
| 		for (var a = 1; initTestOk && a < minPoolSize; a += 10) { | ||||
| 			if (initStartTime.Subtract(DateTime.Now).TotalSeconds > 3) break; //预热耗时超过3秒,退出 | ||||
| 			var b = Math.Min(minPoolSize - a, 10); //每10个预热 | ||||
| 			var initTasks = new Task[b]; | ||||
| 			for (var c = 0; c < b; c++) { | ||||
| 				initTasks[c] = Task.Run(() => { | ||||
| 					try { | ||||
| 						var conn = pool.Get(); | ||||
| 						initConns.Add(conn); | ||||
| 						pool.Policy.OnCheckAvailable(conn); | ||||
| 					} catch { | ||||
| 						initTestOk = false;  //有失败,下一组退出预热 | ||||
| 					} | ||||
| 				}); | ||||
| 			} | ||||
| 			Task.WaitAll(initTasks); | ||||
| 		} | ||||
| 		while (initConns.TryTake(out var conn)) pool.Return(conn); | ||||
| 	} | ||||
| } | ||||
| @@ -1,644 +0,0 @@ | ||||
| using Microsoft.CSharp; | ||||
| using System; | ||||
| using System.CodeDom.Compiler; | ||||
| using System.Collections; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions; | ||||
| using System.Threading; | ||||
|  | ||||
| namespace FreeSql.Generator { | ||||
| 	public class TemplateEngin : IDisposable { | ||||
| 		public interface ITemplateOutput { | ||||
| 			/// <summary> | ||||
| 			///  | ||||
| 			/// </summary> | ||||
| 			/// <param name="tOuTpUt">返回内容</param> | ||||
| 			/// <param name="oPtIoNs">渲染对象</param> | ||||
| 			/// <param name="rEfErErFiLeNaMe">当前文件路径</param> | ||||
| 			/// <param name="tEmPlAtEsEnDeR"></param> | ||||
| 			/// <returns></returns> | ||||
| 			TemplateReturnInfo OuTpUt(StringBuilder tOuTpUt, IDictionary oPtIoNs, string rEfErErFiLeNaMe, TemplateEngin tEmPlAtEsEnDeR); | ||||
| 		} | ||||
| 		public class TemplateReturnInfo { | ||||
| 			public Dictionary<string, int[]> Blocks; | ||||
| 			public StringBuilder Sb; | ||||
| 		} | ||||
| 		public delegate bool TemplateIf(object exp); | ||||
| 		public delegate void TemplatePrint(params object[] parms); | ||||
|  | ||||
| 		private static int _view = 0; | ||||
| 		private static Regex _reg = new Regex(@"\{(\$TEMPLATE__CODE|\/\$TEMPLATE__CODE|import\s+|module\s+|extends\s+|block\s+|include\s+|for\s+|if\s+|#|\/for|elseif|else|\/if|\/block|\/module)([^\}]*)\}", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_forin = new Regex(@"^([\w_]+)\s*,?\s*([\w_]+)?\s+in\s+(.+)", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_foron = new Regex(@"^([\w_]+)\s*,?\s*([\w_]+)?,?\s*([\w_]+)?\s+on\s+(.+)", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_forab = new Regex(@"^([\w_]+)\s+([^,]+)\s*,\s*(.+)", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_miss = new Regex(@"\{\/?miss\}", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_code = new Regex(@"(\{%|%\})", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_syntax = new Regex(@"<(\w+)\s+@(if|for|else)\s*=""([^""]*)""", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_htmltag = new Regex(@"<\/?\w+[^>]*>", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_blank = new Regex(@"\s+", RegexOptions.Compiled); | ||||
| 		private static Regex _reg_complie_undefined = new Regex(@"(当前上下文中不存在名称)?“(\w+)”", RegexOptions.Compiled); | ||||
|  | ||||
| 		private Dictionary<string, ITemplateOutput> _cache = new Dictionary<string, ITemplateOutput>(); | ||||
| 		private object _cache_lock = new object(); | ||||
| 		private string _viewDir; | ||||
| 		private string[] _usings; | ||||
| 		private FileSystemWatcher _fsw = new FileSystemWatcher(); | ||||
|  | ||||
| 		public TemplateEngin(string viewDir, params string[] usings) { | ||||
| 			_viewDir = Utils.TranslateUrl(viewDir); | ||||
| 			_usings = usings; | ||||
| 			_fsw = new FileSystemWatcher(_viewDir); | ||||
| 			_fsw.IncludeSubdirectories = true; | ||||
| 			_fsw.Changed += ViewDirChange; | ||||
| 			_fsw.Renamed += ViewDirChange; | ||||
| 			_fsw.EnableRaisingEvents = true; | ||||
| 		} | ||||
| 		public void Dispose() { | ||||
| 			_fsw.Dispose(); | ||||
| 		} | ||||
| 		void ViewDirChange(object sender, FileSystemEventArgs e) { | ||||
| 			string filename = e.FullPath.ToLower(); | ||||
| 			lock (_cache_lock) { | ||||
| 				_cache.Remove(filename); | ||||
| 			} | ||||
| 		} | ||||
| 		public TemplateReturnInfo RenderFile2(StringBuilder sb, IDictionary options, string filename, string refererFilename) { | ||||
| 			if (filename[0] == '/' || string.IsNullOrEmpty(refererFilename)) refererFilename = _viewDir; | ||||
| 			//else refererFilename = Path.GetDirectoryName(refererFilename); | ||||
| 			string filename2 = Utils.TranslateUrl(filename, refererFilename); | ||||
| 			ITemplateOutput tpl; | ||||
| 			if (_cache.TryGetValue(filename2, out tpl) == false) { | ||||
| 				string tplcode = File.Exists(filename2) == false ? string.Concat("文件不存在 ", filename) : Utils.ReadTextFile(filename2); | ||||
| 				tpl = Parser(tplcode, _usings, options); | ||||
| 				lock (_cache_lock) { | ||||
| 					if (_cache.ContainsKey(filename2) == false) { | ||||
| 						_cache.Add(filename2, tpl); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			try { | ||||
| 				return tpl.OuTpUt(sb, options, filename2, this); | ||||
| 			} catch (Exception ex) { | ||||
| 				TemplateReturnInfo ret = sb == null ? | ||||
| 					new TemplateReturnInfo { Sb = new StringBuilder(), Blocks = new Dictionary<string, int[]>() } : | ||||
| 					new TemplateReturnInfo { Sb = sb, Blocks = new Dictionary<string, int[]>() }; | ||||
| 				ret.Sb.Append(refererFilename); | ||||
| 				ret.Sb.Append(" -> "); | ||||
| 				ret.Sb.Append(filename); | ||||
| 				ret.Sb.Append("\r\n"); | ||||
| 				ret.Sb.Append(ex.Message); | ||||
| 				ret.Sb.Append("\r\n"); | ||||
| 				ret.Sb.Append(ex.StackTrace); | ||||
| 				return ret; | ||||
| 			} | ||||
| 		} | ||||
| 		public string RenderFile(string filename, IDictionary options) { | ||||
| 			TemplateReturnInfo ret = this.RenderFile2(null, options, filename, null); | ||||
| 			return ret.Sb.ToString(); | ||||
| 		} | ||||
| 		private static ITemplateOutput Parser(string tplcode, string[] usings, IDictionary options) { | ||||
| 			int view = Interlocked.Increment(ref _view); | ||||
| 			StringBuilder sb = new StringBuilder(); | ||||
| 			IDictionary options_copy = new Hashtable(); | ||||
| 			foreach (DictionaryEntry options_de in options) options_copy[options_de.Key] = options_de.Value; | ||||
| 			sb.AppendFormat(@" | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions;{1} | ||||
|  | ||||
| //namespace TplDynamicCodeGenerate {{ | ||||
| 	public class TplDynamicCodeGenerate_view{0} : FreeSql.Generator.TemplateEngin.ITemplateOutput {{ | ||||
| 		public FreeSql.Generator.TemplateEngin.TemplateReturnInfo OuTpUt(StringBuilder tOuTpUt, IDictionary oPtIoNs, string rEfErErFiLeNaMe, FreeSql.Generator.TemplateEngin tEmPlAtEsEnDeR) {{ | ||||
| 			FreeSql.Generator.TemplateEngin.TemplateReturnInfo rTn = tOuTpUt == null ?  | ||||
| 				new FreeSql.Generator.TemplateEngin.TemplateReturnInfo {{ Sb = (tOuTpUt = new StringBuilder()), Blocks = new Dictionary<string, int[]>() }} : | ||||
| 				new FreeSql.Generator.TemplateEngin.TemplateReturnInfo {{ Sb = tOuTpUt, Blocks = new Dictionary<string, int[]>() }}; | ||||
| 			Dictionary<string, int[]> TPL__blocks = rTn.Blocks; | ||||
| 			Stack<int[]> TPL__blocks_stack = new Stack<int[]>(); | ||||
| 			int[] TPL__blocks_stack_peek; | ||||
| 			List<IDictionary> TPL__forc = new List<IDictionary>(); | ||||
| 			Func<IDictionary> pRoCeSsOpTiOnS = new Func<IDictionary>(delegate () {{ | ||||
| 				IDictionary nEwoPtIoNs = new Hashtable(); | ||||
| 				foreach (DictionaryEntry oPtIoNs_dE in oPtIoNs) | ||||
| 					nEwoPtIoNs[oPtIoNs_dE.Key] = oPtIoNs_dE.Value; | ||||
| 				foreach (IDictionary TPL__forc_dIc in TPL__forc) | ||||
| 					foreach (DictionaryEntry TPL__forc_dIc_dE in TPL__forc_dIc) | ||||
| 						nEwoPtIoNs[TPL__forc_dIc_dE.Key] = TPL__forc_dIc_dE.Value; | ||||
| 				return nEwoPtIoNs; | ||||
| 			}}); | ||||
| 			FreeSql.Generator.TemplateEngin.TemplateIf tPlIf = delegate(object exp) {{ | ||||
| 				if (exp is bool) return (bool)exp; | ||||
| 				if (exp == null) return false; | ||||
| 				if (exp is int && (int)exp == 0) return false; | ||||
| 				if (exp is string && (string)exp == string.Empty) return false; | ||||
| 				if (exp is long && (long)exp == 0) return false; | ||||
| 				if (exp is short && (short)exp == 0) return false; | ||||
| 				if (exp is byte && (byte)exp == 0) return false; | ||||
| 				if (exp is double && (double)exp == 0) return false; | ||||
| 				if (exp is float && (float)exp == 0) return false; | ||||
| 				if (exp is decimal && (decimal)exp == 0) return false; | ||||
| 				return true; | ||||
| 			}}; | ||||
| 			FreeSql.Generator.TemplateEngin.TemplatePrint print = delegate(object[] pArMs) {{ | ||||
| 				if (pArMs == null || pArMs.Length == 0) return; | ||||
| 				foreach (object pArMs_A in pArMs) if (pArMs_A != null) tOuTpUt.Append(pArMs_A); | ||||
| 			}}; | ||||
| 			FreeSql.Generator.TemplateEngin.TemplatePrint Print = print;", view, usings?.Any() == true ? $"\r\nusing {string.Join(";\r\nusing ", usings)};" : ""); | ||||
|  | ||||
| 			#region {miss}...{/miss}块内容将不被解析 | ||||
| 			string[] tmp_content_arr = _reg_miss.Split(tplcode); | ||||
| 			if (tmp_content_arr.Length > 1) { | ||||
| 				sb.AppendFormat(@" | ||||
| 			string[] TPL__MISS = new string[{0}];", Math.Ceiling(1.0 * (tmp_content_arr.Length - 1) / 2)); | ||||
| 				int miss_len = -1; | ||||
| 				for (int a = 1; a < tmp_content_arr.Length; a += 2) { | ||||
| 					sb.Append(string.Concat(@" | ||||
| 			TPL__MISS[", ++miss_len, @"] = """, Utils.GetConstString(tmp_content_arr[a]), @""";")); | ||||
| 					tmp_content_arr[a] = string.Concat("{#TPL__MISS[", miss_len, "]}"); | ||||
| 				} | ||||
| 				tplcode = string.Join("", tmp_content_arr); | ||||
| 			} | ||||
| 			#endregion | ||||
| 			#region 扩展语法如 <div @if="表达式"></div> | ||||
| 			tplcode = htmlSyntax(tplcode, 3); //<div @if="c#表达式" @for="index 1,100"></div> | ||||
| 											  //处理 {% %} 块 c#代码 | ||||
| 			tmp_content_arr = _reg_code.Split(tplcode); | ||||
| 			if (tmp_content_arr.Length == 1) { | ||||
| 				tplcode = Utils.GetConstString(tplcode) | ||||
| 					.Replace("{%", "{$TEMPLATE__CODE}") | ||||
| 					.Replace("%}", "{/$TEMPLATE__CODE}"); | ||||
| 			} else { | ||||
| 				tmp_content_arr[0] = Utils.GetConstString(tmp_content_arr[0]); | ||||
| 				for (int a = 1; a < tmp_content_arr.Length; a += 4) { | ||||
| 					tmp_content_arr[a] = "{$TEMPLATE__CODE}"; | ||||
| 					tmp_content_arr[a + 2] = "{/$TEMPLATE__CODE}"; | ||||
| 					tmp_content_arr[a + 3] = Utils.GetConstString(tmp_content_arr[a + 3]); | ||||
| 				} | ||||
| 				tplcode = string.Join("", tmp_content_arr); | ||||
| 			} | ||||
| 			#endregion | ||||
| 			sb.Append(@" | ||||
| 			tOuTpUt.Append("""); | ||||
|  | ||||
| 			string error = null; | ||||
| 			int tpl_tmpid = 0; | ||||
| 			int forc_i = 0; | ||||
| 			string extends = null; | ||||
| 			Stack<string> codeTree = new Stack<string>(); | ||||
| 			Stack<string> forEndRepl = new Stack<string>(); | ||||
| 			sb.Append(_reg.Replace(tplcode, delegate (Match m) { | ||||
| 				string _0 = m.Groups[0].Value; | ||||
| 				if (!string.IsNullOrEmpty(error)) return _0; | ||||
|  | ||||
| 				string _1 = m.Groups[1].Value.Trim(' ', '\t'); | ||||
| 				string _2 = m.Groups[2].Value | ||||
| 					.Replace("\\\\", "\\") | ||||
| 					.Replace("\\\"", "\""); | ||||
| 				_2 = Utils.ReplaceSingleQuote(_2); | ||||
|  | ||||
| 				switch (_1) { | ||||
| 					#region $TEMPLATE__CODE-------------------------------------------------- | ||||
| 					case "$TEMPLATE__CODE": | ||||
| 						codeTree.Push(_1); | ||||
| 						return @"""); | ||||
| "; | ||||
| 					case "/$TEMPLATE__CODE": | ||||
| 						string pop = codeTree.Pop(); | ||||
| 						if (pop != "$TEMPLATE__CODE") { | ||||
| 							codeTree.Push(pop); | ||||
| 							error = "编译出错,{% 与 %} 并没有配对"; | ||||
| 							return _0; | ||||
| 						} | ||||
| 						return @" | ||||
| 			tOuTpUt.Append("""; | ||||
| 					#endregion | ||||
| 					case "include": | ||||
| 						return string.Format(@"""); | ||||
| tEmPlAtEsEnDeR.RenderFile2(tOuTpUt, pRoCeSsOpTiOnS(), ""{0}"", rEfErErFiLeNaMe); | ||||
| 			tOuTpUt.Append(""", _2); | ||||
| 					case "import": | ||||
| 						return _0; | ||||
| 					case "module": | ||||
| 						return _0; | ||||
| 					case "/module": | ||||
| 						return _0; | ||||
| 					case "extends": | ||||
| 						//{extends ../inc/layout.html} | ||||
| 						if (string.IsNullOrEmpty(extends) == false) return _0; | ||||
| 						extends = _2; | ||||
| 						return string.Empty; | ||||
| 					case "block": | ||||
| 						codeTree.Push("block"); | ||||
| 						return string.Format(@"""); | ||||
| TPL__blocks_stack_peek = new int[] {{ tOuTpUt.Length, 0 }}; | ||||
| TPL__blocks_stack.Push(TPL__blocks_stack_peek); | ||||
| TPL__blocks.Add(""{0}"", TPL__blocks_stack_peek); | ||||
| tOuTpUt.Append(""", _2.Trim(' ', '\t')); | ||||
| 					case "/block": | ||||
| 						codeTreeEnd(codeTree, "block"); | ||||
| 						return @"""); | ||||
| TPL__blocks_stack_peek = TPL__blocks_stack.Pop(); | ||||
| TPL__blocks_stack_peek[1] = tOuTpUt.Length - TPL__blocks_stack_peek[0]; | ||||
| tOuTpUt.Append("""; | ||||
|  | ||||
| 					#region ##--------------------------------------------------------- | ||||
| 					case "#": | ||||
| 						if (_2[0] == '#') | ||||
| 							return string.Format(@"""); | ||||
| 			try {{ Print({0}); }} catch {{ }} | ||||
| 			tOuTpUt.Append(""", _2.Substring(1)); | ||||
| 						return string.Format(@"""); | ||||
| 			Print({0}); | ||||
| 			tOuTpUt.Append(""", _2); | ||||
| 					#endregion | ||||
| 					#region for-------------------------------------------------------- | ||||
| 					case "for": | ||||
| 						forc_i++; | ||||
| 						int cur_tpl_tmpid = tpl_tmpid; | ||||
| 						string sb_endRepl = string.Empty; | ||||
| 						StringBuilder sbfor = new StringBuilder(); | ||||
| 						sbfor.Append(@""");"); | ||||
| 						Match mfor = _reg_forin.Match(_2); | ||||
| 						if (mfor.Success) { | ||||
| 							string mfor1 = mfor.Groups[1].Value.Trim(' ', '\t'); | ||||
| 							string mfor2 = mfor.Groups[2].Value.Trim(' ', '\t'); | ||||
| 							sbfor.AppendFormat(@" | ||||
| //new Action(delegate () {{ | ||||
| 	IDictionary TPL__tmp{0} = new Hashtable(); | ||||
| 	TPL__forc.Add(TPL__tmp{0}); | ||||
| 	var TPL__tmp{1} = {3}; | ||||
| 	var TPL__tmp{2} = {4};", ++tpl_tmpid, ++tpl_tmpid, ++tpl_tmpid, mfor.Groups[3].Value, mfor1); | ||||
| 							sb_endRepl = string.Concat(sb_endRepl, string.Format(@" | ||||
| 	{0} = TPL__tmp{1};", mfor1, cur_tpl_tmpid + 3)); | ||||
| 							if (options_copy.Contains(mfor1) == false) options_copy[mfor1] = null; | ||||
| 							if (!string.IsNullOrEmpty(mfor2)) { | ||||
| 								sbfor.AppendFormat(@" | ||||
| 	var TPL__tmp{1} = {0}; | ||||
| 	{0} = 0;", mfor2, ++tpl_tmpid); | ||||
| 								sb_endRepl = string.Concat(sb_endRepl, string.Format(@" | ||||
| 	{0} = TPL__tmp{1};", mfor2, tpl_tmpid)); | ||||
| 								if (options_copy.Contains(mfor2) == false) options_copy[mfor2] = null; | ||||
| 							} | ||||
| 							sbfor.AppendFormat(@" | ||||
| 	if (TPL__tmp{1} != null) | ||||
| 	foreach (var TPL__tmp{0} in TPL__tmp{1}) {{", ++tpl_tmpid, cur_tpl_tmpid + 2); | ||||
| 							if (!string.IsNullOrEmpty(mfor2)) | ||||
| 								sbfor.AppendFormat(@" | ||||
| 		TPL__tmp{1}[""{0}""] = ++ {0};", mfor2, cur_tpl_tmpid + 1); | ||||
| 							sbfor.AppendFormat(@" | ||||
| 		TPL__tmp{1}[""{0}""] = TPL__tmp{2}; | ||||
| 		{0} = TPL__tmp{2}; | ||||
| 		tOuTpUt.Append(""", mfor1, cur_tpl_tmpid + 1, tpl_tmpid); | ||||
| 							codeTree.Push("for"); | ||||
| 							forEndRepl.Push(sb_endRepl); | ||||
| 							return sbfor.ToString(); | ||||
| 						} | ||||
| 						mfor = _reg_foron.Match(_2); | ||||
| 						if (mfor.Success) { | ||||
| 							string mfor1 = mfor.Groups[1].Value.Trim(' ', '\t'); | ||||
| 							string mfor2 = mfor.Groups[2].Value.Trim(' ', '\t'); | ||||
| 							string mfor3 = mfor.Groups[3].Value.Trim(' ', '\t'); | ||||
| 							sbfor.AppendFormat(@" | ||||
| //new Action(delegate () {{ | ||||
| 	IDictionary TPL__tmp{0} = new Hashtable(); | ||||
| 	TPL__forc.Add(TPL__tmp{0}); | ||||
| 	var TPL__tmp{1} = {3}; | ||||
| 	var TPL__tmp{2} = {4};", ++tpl_tmpid, ++tpl_tmpid, ++tpl_tmpid, mfor.Groups[4].Value, mfor1); | ||||
| 							sb_endRepl = string.Concat(sb_endRepl, string.Format(@" | ||||
| 	{0} = TPL__tmp{1};", mfor1, cur_tpl_tmpid + 3)); | ||||
| 							if (options_copy.Contains(mfor1) == false) options_copy[mfor1] = null; | ||||
| 							if (!string.IsNullOrEmpty(mfor2)) { | ||||
| 								sbfor.AppendFormat(@" | ||||
| 	var TPL__tmp{1} = {0};", mfor2, ++tpl_tmpid); | ||||
| 								sb_endRepl = string.Concat(sb_endRepl, string.Format(@" | ||||
| 	{0} = TPL__tmp{1};", mfor2, tpl_tmpid)); | ||||
| 								if (options_copy.Contains(mfor2) == false) options_copy[mfor2] = null; | ||||
| 							} | ||||
| 							if (!string.IsNullOrEmpty(mfor3)) { | ||||
| 								sbfor.AppendFormat(@" | ||||
| 	var TPL__tmp{1} = {0}; | ||||
| 	{0} = 0;", mfor3, ++tpl_tmpid); | ||||
| 								sb_endRepl = string.Concat(sb_endRepl, string.Format(@" | ||||
| 	{0} = TPL__tmp{1};", mfor3, tpl_tmpid)); | ||||
| 								if (options_copy.Contains(mfor3) == false) options_copy[mfor3] = null; | ||||
| 							} | ||||
| 							sbfor.AppendFormat(@" | ||||
| 	if (TPL__tmp{2} != null) | ||||
| 	foreach (DictionaryEntry TPL__tmp{1} in TPL__tmp{2}) {{ | ||||
| 		{0} = TPL__tmp{1}.Key; | ||||
| 		TPL__tmp{3}[""{0}""] = {0};", mfor1, ++tpl_tmpid, cur_tpl_tmpid + 2, cur_tpl_tmpid + 1); | ||||
| 							if (!string.IsNullOrEmpty(mfor2)) | ||||
| 								sbfor.AppendFormat(@" | ||||
| 		{0} = TPL__tmp{1}.Value; | ||||
| 		TPL__tmp{2}[""{0}""] = {0};", mfor2, tpl_tmpid, cur_tpl_tmpid + 1); | ||||
| 							if (!string.IsNullOrEmpty(mfor3)) | ||||
| 								sbfor.AppendFormat(@" | ||||
| 		TPL__tmp{1}[""{0}""] = ++ {0};", mfor3, cur_tpl_tmpid + 1); | ||||
| 							sbfor.AppendFormat(@" | ||||
| 		tOuTpUt.Append("""); | ||||
| 							codeTree.Push("for"); | ||||
| 							forEndRepl.Push(sb_endRepl); | ||||
| 							return sbfor.ToString(); | ||||
| 						} | ||||
| 						mfor = _reg_forab.Match(_2); | ||||
| 						if (mfor.Success) { | ||||
| 							string mfor1 = mfor.Groups[1].Value.Trim(' ', '\t'); | ||||
| 							sbfor.AppendFormat(@" | ||||
| //new Action(delegate () {{ | ||||
| 	IDictionary TPL__tmp{0} = new Hashtable(); | ||||
| 	TPL__forc.Add(TPL__tmp{0}); | ||||
| 	var TPL__tmp{1} = {5}; | ||||
| 	{5} = {3} - 1; | ||||
| 	if ({5} == null) {5} = 0; | ||||
| 	var TPL__tmp{2} = {4} + 1; | ||||
| 	while (++{5} < TPL__tmp{2}) {{ | ||||
| 		TPL__tmp{0}[""{5}""] = {5}; | ||||
| 		tOuTpUt.Append(""", ++tpl_tmpid, ++tpl_tmpid, ++tpl_tmpid, mfor.Groups[2].Value, mfor.Groups[3].Value, mfor1); | ||||
| 							sb_endRepl = string.Concat(sb_endRepl, string.Format(@" | ||||
| 	{0} = TPL__tmp{1};", mfor1, cur_tpl_tmpid + 1)); | ||||
| 							if (options_copy.Contains(mfor1) == false) options_copy[mfor1] = null; | ||||
| 							codeTree.Push("for"); | ||||
| 							forEndRepl.Push(sb_endRepl); | ||||
| 							return sbfor.ToString(); | ||||
| 						} | ||||
| 						return _0; | ||||
| 					case "/for": | ||||
| 						if (--forc_i < 0) return _0; | ||||
| 						codeTreeEnd(codeTree, "for"); | ||||
| 						return string.Format(@"""); | ||||
| 	}}{0} | ||||
| 	TPL__forc.RemoveAt(TPL__forc.Count - 1); | ||||
| //}})(); | ||||
| 			tOuTpUt.Append(""", forEndRepl.Pop()); | ||||
| 					#endregion | ||||
| 					#region if--------------------------------------------------------- | ||||
| 					case "if": | ||||
| 						codeTree.Push("if"); | ||||
| 						return string.Format(@"""); | ||||
| 			if ({1}tPlIf({0})) {{ | ||||
| 				tOuTpUt.Append(""", _2[0] == '!' ? _2.Substring(1) : _2, _2[0] == '!' ? '!' : ' '); | ||||
| 					case "elseif": | ||||
| 						codeTreeEnd(codeTree, "if"); | ||||
| 						codeTree.Push("if"); | ||||
| 						return string.Format(@"""); | ||||
| 			}} else if ({1}tPlIf({0})) {{ | ||||
| 				tOuTpUt.Append(""", _2[0] == '!' ? _2.Substring(1) : _2, _2[0] == '!' ? '!' : ' '); | ||||
| 					case "else": | ||||
| 						codeTreeEnd(codeTree, "if"); | ||||
| 						codeTree.Push("if"); | ||||
| 						return @"""); | ||||
| 			} else { | ||||
| 			tOuTpUt.Append("""; | ||||
| 					case "/if": | ||||
| 						codeTreeEnd(codeTree, "if"); | ||||
| 						return @"""); | ||||
| 			} | ||||
| 			tOuTpUt.Append("""; | ||||
| 						#endregion | ||||
| 				} | ||||
| 				return _0; | ||||
| 			})); | ||||
|  | ||||
| 			sb.Append(@""");"); | ||||
| 			if (string.IsNullOrEmpty(extends) == false) { | ||||
| 				sb.AppendFormat(@" | ||||
| FreeSql.Generator.TemplateEngin.TemplateReturnInfo eXtEnDs_ReT = tEmPlAtEsEnDeR.RenderFile2(null, pRoCeSsOpTiOnS(), ""{0}"", rEfErErFiLeNaMe); | ||||
| string rTn_Sb_string = rTn.Sb.ToString(); | ||||
| foreach(string eXtEnDs_ReT_blocks_key in eXtEnDs_ReT.Blocks.Keys) {{ | ||||
| 	if (rTn.Blocks.ContainsKey(eXtEnDs_ReT_blocks_key)) {{ | ||||
| 		int[] eXtEnDs_ReT_blocks_value = eXtEnDs_ReT.Blocks[eXtEnDs_ReT_blocks_key]; | ||||
| 		eXtEnDs_ReT.Sb.Remove(eXtEnDs_ReT_blocks_value[0], eXtEnDs_ReT_blocks_value[1]); | ||||
| 		int[] rTn_blocks_value = rTn.Blocks[eXtEnDs_ReT_blocks_key]; | ||||
| 		eXtEnDs_ReT.Sb.Insert(eXtEnDs_ReT_blocks_value[0], rTn_Sb_string.Substring(rTn_blocks_value[0], rTn_blocks_value[1])); | ||||
| 		foreach(string eXtEnDs_ReT_blocks_keyb in eXtEnDs_ReT.Blocks.Keys) {{ | ||||
| 			if (eXtEnDs_ReT_blocks_keyb == eXtEnDs_ReT_blocks_key) continue; | ||||
| 			int[] eXtEnDs_ReT_blocks_valueb = eXtEnDs_ReT.Blocks[eXtEnDs_ReT_blocks_keyb]; | ||||
| 			if (eXtEnDs_ReT_blocks_valueb[0] >= eXtEnDs_ReT_blocks_value[0]) | ||||
| 				eXtEnDs_ReT_blocks_valueb[0] = eXtEnDs_ReT_blocks_valueb[0] - eXtEnDs_ReT_blocks_value[1] + rTn_blocks_value[1]; | ||||
| 		}} | ||||
| 		eXtEnDs_ReT_blocks_value[1] = rTn_blocks_value[1]; | ||||
| 	}} | ||||
| }} | ||||
| return eXtEnDs_ReT; | ||||
| ", extends); | ||||
| 			} else { | ||||
| 				sb.Append(@" | ||||
| return rTn;"); | ||||
| 			} | ||||
| 			sb.Append(@" | ||||
| 		} | ||||
| 	} | ||||
| //} | ||||
| "); | ||||
| 			var str = "FreeSql.Generator.TemplateEngin.TemplatePrint Print = print;"; | ||||
| 			int dim_idx = sb.ToString().IndexOf(str) + str.Length; | ||||
| 			foreach (string dic_name in options_copy.Keys) { | ||||
| 				sb.Insert(dim_idx, string.Format(@" | ||||
| 			dynamic {0} = oPtIoNs[""{0}""];", dic_name)); | ||||
| 			} | ||||
| 			//Console.WriteLine(sb.ToString()); | ||||
| 			return Complie(sb.ToString(), @"TplDynamicCodeGenerate_view" + view); | ||||
| 		} | ||||
| 		private static string codeTreeEnd(Stack<string> codeTree, string tag) { | ||||
| 			string ret = string.Empty; | ||||
| 			Stack<int> pop = new Stack<int>(); | ||||
| 			foreach (string ct in codeTree) { | ||||
| 				if (ct == "import" || | ||||
| 					ct == "include") { | ||||
| 					pop.Push(1); | ||||
| 				} else if (ct == tag) { | ||||
| 					pop.Push(2); | ||||
| 					break; | ||||
| 				} else { | ||||
| 					if (string.IsNullOrEmpty(tag) == false) pop.Clear(); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			if (pop.Count == 0 && string.IsNullOrEmpty(tag) == false) | ||||
| 				return string.Concat("语法错误,{", tag, "} {/", tag, "} 并没配对"); | ||||
| 			while (pop.Count > 0 && pop.Pop() > 0) codeTree.Pop(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		#region htmlSyntax | ||||
| 		private static string htmlSyntax(string tplcode, int num) { | ||||
|  | ||||
| 			while (num-- > 0) { | ||||
| 				string[] arr = _reg_syntax.Split(tplcode); | ||||
|  | ||||
| 				if (arr.Length == 1) break; | ||||
| 				for (int a = 1; a < arr.Length; a += 4) { | ||||
| 					string tag = string.Concat('<', arr[a]); | ||||
| 					string end = string.Concat("</", arr[a], '>'); | ||||
| 					int fc = 1; | ||||
| 					for (int b = a; fc > 0 && b < arr.Length; b += 4) { | ||||
| 						if (b > a && arr[a].ToLower() == arr[b].ToLower()) fc++; | ||||
| 						int bpos = 0; | ||||
| 						while (true) { | ||||
| 							int fa = arr[b + 3].IndexOf(tag, bpos); | ||||
| 							int fb = arr[b + 3].IndexOf(end, bpos); | ||||
| 							if (b == a) { | ||||
| 								var z = arr[b + 3].IndexOf("/>"); | ||||
| 								if ((fb == -1 || z < fb) && z != -1) { | ||||
| 									var y = arr[b + 3].Substring(0, z + 2); | ||||
| 									if (_reg_htmltag.IsMatch(y) == false) | ||||
| 										fb = z - end.Length + 2; | ||||
| 								} | ||||
| 							} | ||||
| 							if (fa == -1 && fb == -1) break; | ||||
| 							if (fa != -1 && (fa < fb || fb == -1)) { | ||||
| 								fc++; | ||||
| 								bpos = fa + tag.Length; | ||||
| 								continue; | ||||
| 							} | ||||
| 							if (fb != -1) fc--; | ||||
| 							if (fc <= 0) { | ||||
| 								var a1 = arr[a + 1]; | ||||
| 								var end3 = string.Concat("{/", a1, "}"); | ||||
| 								if (a1.ToLower() == "else") { | ||||
| 									if (_reg_blank.Replace(arr[a - 4 + 3], "").EndsWith("{/if}", StringComparison.CurrentCultureIgnoreCase) == true) { | ||||
| 										var idx = arr[a - 4 + 3].IndexOf("{/if}"); | ||||
| 										arr[a - 4 + 3] = string.Concat(arr[a - 4 + 3].Substring(0, idx), arr[a - 4 + 3].Substring(idx + 5)); | ||||
| 										//如果 @else="有条件内容",则变换成 elseif 条件内容 | ||||
| 										if (_reg_blank.Replace(arr[a + 2], "").Length > 0) a1 = "elseif"; | ||||
| 										end3 = "{/if}"; | ||||
| 									} else { | ||||
| 										arr[a] = string.Concat("指令 @", arr[a + 1], "='", arr[a + 2], "' 没紧接着 if/else 指令之后,无效. <", arr[a]); | ||||
| 										arr[a + 1] = arr[a + 2] = string.Empty; | ||||
| 									} | ||||
| 								} | ||||
| 								if (arr[a + 1].Length > 0) { | ||||
| 									if (_reg_blank.Replace(arr[a + 2], "").Length > 0 || a1.ToLower() == "else") { | ||||
| 										arr[b + 3] = string.Concat(arr[b + 3].Substring(0, fb + end.Length), end3, arr[b + 3].Substring(fb + end.Length)); | ||||
| 										arr[a] = string.Concat("{", a1, " ", arr[a + 2], "}<", arr[a]); | ||||
| 										arr[a + 1] = arr[a + 2] = string.Empty; | ||||
| 									} else { | ||||
| 										arr[a] = string.Concat('<', arr[a]); | ||||
| 										arr[a + 1] = arr[a + 2] = string.Empty; | ||||
| 									} | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 							bpos = fb + end.Length; | ||||
| 						} | ||||
| 					} | ||||
| 					if (fc > 0) { | ||||
| 						arr[a] = string.Concat("不严谨的html格式,请检查 ", arr[a], " 的结束标签, @", arr[a + 1], "='", arr[a + 2], "' 指令无效. <", arr[a]); | ||||
| 						arr[a + 1] = arr[a + 2] = string.Empty; | ||||
| 					} | ||||
| 				} | ||||
| 				if (arr.Length > 0) tplcode = string.Join(string.Empty, arr); | ||||
| 			} | ||||
| 			return tplcode; | ||||
| 		} | ||||
| 		#endregion | ||||
| 		#region Complie | ||||
| 		private static ITemplateOutput Complie(string cscode, string typename) { | ||||
| 			var assemly = _compiler.Value.CompileCode(cscode); | ||||
| 			var type = assemly.DefinedTypes.Where(a => a.FullName.EndsWith(typename)).FirstOrDefault(); | ||||
| 			return Activator.CreateInstance(type) as ITemplateOutput; | ||||
| 		} | ||||
| 		internal static Lazy<CSScriptLib.RoslynEvaluator> _compiler = new Lazy<CSScriptLib.RoslynEvaluator>(() => { | ||||
| 			//var dlls = Directory.GetFiles(Directory.GetParent(Type.GetType("IFreeSql, FreeSql").Assembly.Location).FullName, "*.dll"); | ||||
| 			var compiler = new CSScriptLib.RoslynEvaluator(); | ||||
| 			compiler.DisableReferencingFromCode = false; | ||||
| 			//compiler.DebugBuild = true; | ||||
| 			//foreach (var dll in dlls) { | ||||
| 			//	Console.WriteLine(dll); | ||||
| 			//	var ass = Assembly.LoadFile(dll); | ||||
| 			//	compiler.ReferenceAssembly(ass); | ||||
| 			//} | ||||
| 			compiler | ||||
| 				.ReferenceAssemblyOf<IFreeSql>() | ||||
| 				.ReferenceDomainAssemblies(); | ||||
| 			return compiler; | ||||
| 		}); | ||||
|  | ||||
| 		#endregion | ||||
|  | ||||
| 		#region Utils | ||||
| 		public class Utils { | ||||
| 			public static string ReplaceSingleQuote(object exp) { | ||||
| 				//将 ' 转换成 " | ||||
| 				string exp2 = string.Concat(exp); | ||||
| 				int quote_pos = -1; | ||||
| 				while (true) { | ||||
| 					int first_pos = quote_pos = exp2.IndexOf('\'', quote_pos + 1); | ||||
| 					if (quote_pos == -1) break; | ||||
| 					while (true) { | ||||
| 						quote_pos = exp2.IndexOf('\'', quote_pos + 1); | ||||
| 						if (quote_pos == -1) break; | ||||
| 						int r_cout = 0; | ||||
| 						for (int p = 1; true; p++) { | ||||
| 							if (exp2[quote_pos - p] == '\\') r_cout++; | ||||
| 							else break; | ||||
| 						} | ||||
| 						if (r_cout % 2 == 0/* && quote_pos - first_pos > 2*/) { | ||||
| 							string str1 = exp2.Substring(0, first_pos); | ||||
| 							string str2 = exp2.Substring(first_pos + 1, quote_pos - first_pos - 1); | ||||
| 							string str3 = exp2.Substring(quote_pos + 1); | ||||
| 							string str4 = str2.Replace("\"", "\\\""); | ||||
| 							quote_pos += str4.Length - str2.Length; | ||||
| 							exp2 = string.Concat(str1, "\"", str4, "\"", str3); | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 					if (quote_pos == -1) break; | ||||
| 				} | ||||
| 				return exp2; | ||||
| 			} | ||||
| 			public static string GetConstString(object obj) { | ||||
| 				return string.Concat(obj) | ||||
| 					.Replace("\\", "\\\\") | ||||
| 					.Replace("\"", "\\\"") | ||||
| 					.Replace("\r", "\\r") | ||||
| 					.Replace("\n", "\\n"); | ||||
| 			} | ||||
|  | ||||
| 			public static string ReadTextFile(string path) { | ||||
| 				byte[] bytes = ReadFile(path); | ||||
| 				return Encoding.UTF8.GetString(bytes).TrimStart((char)65279); | ||||
| 			} | ||||
| 			public static byte[] ReadFile(string path) { | ||||
| 				if (File.Exists(path)) { | ||||
| 					string destFileName = Path.GetTempFileName(); | ||||
| 					File.Copy(path, destFileName, true); | ||||
| 					int read = 0; | ||||
| 					byte[] data = new byte[1024]; | ||||
| 					using (MemoryStream ms = new MemoryStream()) { | ||||
| 						using (FileStream fs = new FileStream(destFileName, FileMode.OpenOrCreate, FileAccess.Read)) { | ||||
| 							do { | ||||
| 								read = fs.Read(data, 0, data.Length); | ||||
| 								if (read <= 0) break; | ||||
| 								ms.Write(data, 0, read); | ||||
| 							} while (true); | ||||
| 						} | ||||
| 						File.Delete(destFileName); | ||||
| 						data = ms.ToArray(); | ||||
| 					} | ||||
| 					return data; | ||||
| 				} | ||||
| 				return new byte[] { }; | ||||
| 			} | ||||
| 			public static string TranslateUrl(string url) { | ||||
| 				return TranslateUrl(url, null); | ||||
| 			} | ||||
| 			public static string TranslateUrl(string url, string baseDir) { | ||||
| 				if (string.IsNullOrEmpty(baseDir)) baseDir = AppContext.BaseDirectory + "/"; | ||||
| 				if (string.IsNullOrEmpty(url)) return Path.GetDirectoryName(baseDir); | ||||
| 				if (url.StartsWith("~/")) url = url.Substring(1); | ||||
| 				if (url.StartsWith("/")) return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(baseDir), url.TrimStart('/'))); | ||||
| 				if (url.StartsWith("\\")) return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(baseDir), url.TrimStart('\\'))); | ||||
| 				if (url.IndexOf(":\\") != -1) return url; | ||||
| 				return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(baseDir), url)); | ||||
| 			} | ||||
| 		} | ||||
| 		#endregion | ||||
| 	} | ||||
| } | ||||
| @@ -1,72 +0,0 @@ | ||||
| using FreeSql.DatabaseModel; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions; | ||||
|  | ||||
| namespace FreeSql.Generator { | ||||
| 	public class TemplateGenerator { | ||||
|  | ||||
| 		public void Build(IDbFirst dbfirst, string templateDirectory, string outputDirectory, params string[] database) { | ||||
| 			if (dbfirst == null) throw new ArgumentException("dbfirst 参数不能为 null"); | ||||
| 			if (string.IsNullOrEmpty(templateDirectory) || Directory.Exists(templateDirectory) == false) throw new ArgumentException("templateDirectory 目录不存在"); | ||||
| 			if (string.IsNullOrEmpty(templateDirectory)) throw new ArgumentException("outputDirectory 不能为 null"); | ||||
| 			if (database == null || database.Any() == false) throw new ArgumentException("database 参数不能为空"); | ||||
| 			if (Directory.Exists(outputDirectory) == false) Directory.CreateDirectory(outputDirectory); | ||||
| 			templateDirectory = new DirectoryInfo(templateDirectory).FullName; | ||||
| 			outputDirectory = new DirectoryInfo(outputDirectory).FullName; | ||||
| 			if (templateDirectory.IndexOf(outputDirectory, StringComparison.CurrentCultureIgnoreCase) != -1) throw new ArgumentException("outputDirectory 目录不能设置在 templateDirectory 目录内"); | ||||
| 			var tables = dbfirst.GetTablesByDatabase(database); | ||||
| 			var tpl = new TemplateEngin(templateDirectory, "FreeSql", "FreeSql.DatabaseModel"); | ||||
| 			BuildEachDirectory(templateDirectory, outputDirectory, tpl, dbfirst, tables); | ||||
| 			tpl.Dispose(); | ||||
| 		} | ||||
|  | ||||
| 		void BuildEachDirectory(string templateDirectory, string outputDirectory, TemplateEngin tpl, IDbFirst dbfirst, List<DbTableInfo> tables) { | ||||
| 			if (Directory.Exists(outputDirectory) == false) Directory.CreateDirectory(outputDirectory); | ||||
| 			var files = Directory.GetFiles(templateDirectory); | ||||
| 			foreach (var file in files) { | ||||
| 				var fi = new FileInfo(file); | ||||
| 				if (string.Compare(fi.Extension, ".FreeSql", true) == 0) { | ||||
| 					var outputExtension = "." + fi.Name.Split('.')[1]; | ||||
| 					if (fi.Name.StartsWith("for-table.")) { | ||||
| 						foreach (var table in tables) { | ||||
| 							var result = tpl.RenderFile(file, new Dictionary<string, object>() { { "table", table }, { "dbfirst", dbfirst } }); | ||||
| 							if (result.EndsWith("return;")) continue; | ||||
| 							var outputName = table.Name + outputExtension; | ||||
| 							var mcls = Regex.Match(result, @"\s+class\s+(\w+)"); | ||||
| 							if (mcls.Success) outputName = mcls.Groups[1].Value + outputExtension; | ||||
| 							var outputStream = Encoding.UTF8.GetBytes(result); | ||||
| 							var fullname = outputDirectory + "/" + outputName; | ||||
| 							if (File.Exists(fullname)) File.Delete(fullname); | ||||
| 							using (var outfs = File.Open(fullname, FileMode.OpenOrCreate, FileAccess.Write)) { | ||||
| 								outfs.Write(outputStream, 0, outputStream.Length); | ||||
| 								outfs.Close(); | ||||
| 							} | ||||
| 						} | ||||
| 						continue; | ||||
| 					} else { | ||||
| 						var result = tpl.RenderFile(file, new Dictionary<string, object>() { { "tables", tables }, { "dbfirst", dbfirst } }); | ||||
| 						var outputName = fi.Name; | ||||
| 						var mcls = Regex.Match(result, @"\s+class\s+(\w+)"); | ||||
| 						if (mcls.Success) outputName = mcls.Groups[1].Value + outputExtension; | ||||
| 						var outputStream = Encoding.UTF8.GetBytes(result); | ||||
| 						var fullname = outputDirectory + "/" + outputName; | ||||
| 						if (File.Exists(fullname)) File.Delete(fullname); | ||||
| 						using (var outfs = File.Open(fullname, FileMode.OpenOrCreate, FileAccess.Write)) { | ||||
| 							outfs.Write(outputStream, 0, outputStream.Length); | ||||
| 							outfs.Close(); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				File.Copy(file, outputDirectory + file.Replace(templateDirectory, ""), true); | ||||
| 			} | ||||
| 			var dirs = Directory.GetDirectories(templateDirectory); | ||||
| 			foreach(var dir in dirs) { | ||||
| 				BuildEachDirectory(dir, outputDirectory +  dir.Replace(templateDirectory, ""), tpl, dbfirst, tables); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -108,13 +108,6 @@ namespace FreeSql { | ||||
| 		/// </summary> | ||||
| 		/// <returns></returns> | ||||
| 		TSelect Master(); | ||||
| 		/// <summary> | ||||
| 		/// 缓存查询结果 | ||||
| 		/// </summary> | ||||
| 		/// <param name="seconds">缓存秒数</param> | ||||
| 		/// <param name="key">缓存key</param> | ||||
| 		/// <returns></returns> | ||||
| 		TSelect Caching(int seconds, string key = null); | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 左联查询,使用导航属性自动生成SQL | ||||
|   | ||||
| @@ -46,11 +46,6 @@ namespace FreeSql { | ||||
| 		/// 当前线程的事务 | ||||
| 		/// </summary> | ||||
| 		DbTransaction TransactionCurrentThread { get; } | ||||
| 		/// <summary> | ||||
| 		/// 事务完成前预删除缓存 | ||||
| 		/// </summary> | ||||
| 		/// <param name="keys"></param> | ||||
| 		void TransactionPreRemoveCache(params string[] keys); | ||||
| 		#endregion | ||||
|  | ||||
| 		/// <summary> | ||||
|   | ||||
| @@ -1,108 +0,0 @@ | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql { | ||||
| 	public interface ICache { | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 缓存数据时序列化方法,若无设置则默认使用 Json.net | ||||
| 		/// </summary> | ||||
| 		Func<object, string> Serialize { get; set; } | ||||
| 		/// <summary> | ||||
| 		/// 获取缓存数据时反序列化方法,若无设置则默认使用 Json.net | ||||
| 		/// </summary> | ||||
| 		Func<string, Type, object> Deserialize { get; set; } | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 缓存可序列化数据 | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T"></typeparam> | ||||
| 		/// <param name="key">缓存键</param> | ||||
| 		/// <param name="data">可序列化数据</param> | ||||
| 		/// <param name="timeoutSeconds">缓存秒数,<=0时永久缓存</param> | ||||
| 		void Set<T>(string key, T data, int timeoutSeconds = 0); | ||||
| 		/// <summary> | ||||
| 		/// 循环或批量获取缓存数据 | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T"></typeparam> | ||||
| 		/// <param name="key"></param> | ||||
| 		/// <returns></returns> | ||||
| 		T Get<T>(string key); | ||||
| 		/// <summary> | ||||
| 		/// 循环或批量获取缓存数据 | ||||
| 		/// </summary> | ||||
| 		/// <param name="key"></param> | ||||
| 		/// <returns></returns> | ||||
| 		string Get(string key); | ||||
| 		/// <summary> | ||||
| 		/// 循环或批量删除缓存键 | ||||
| 		/// </summary> | ||||
| 		/// <param name="keys">缓存键[数组]</param> | ||||
| 		void Remove(params string[] keys); | ||||
| 		/// <summary> | ||||
| 		/// 缓存壳 | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T">缓存类型</typeparam> | ||||
| 		/// <param name="key">缓存键</param> | ||||
| 		/// <param name="timeoutSeconds">缓存秒数</param> | ||||
| 		/// <param name="getData">获取源数据的函数</param> | ||||
| 		/// <returns></returns> | ||||
| 		T Shell<T>(string key, int timeoutSeconds, Func<T> getData); | ||||
| 		/// <summary> | ||||
| 		/// 缓存壳(哈希表) | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T">缓存类型</typeparam> | ||||
| 		/// <param name="key">缓存键</param> | ||||
| 		/// <param name="field">字段</param> | ||||
| 		/// <param name="timeoutSeconds">缓存秒数</param> | ||||
| 		/// <param name="getData">获取源数据的函数</param> | ||||
| 		/// <returns></returns> | ||||
| 		T Shell<T>(string key, string field, int timeoutSeconds, Func<T> getData); | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 缓存可序列化数据 | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T"></typeparam> | ||||
| 		/// <param name="key">缓存键</param> | ||||
| 		/// <param name="data">可序列化数据</param> | ||||
| 		/// <param name="timeoutSeconds">缓存秒数,<=0时永久缓存</param> | ||||
| 		Task SetAsync<T>(string key, T data, int timeoutSeconds = 0); | ||||
| 		/// <summary> | ||||
| 		/// 循环或批量获取缓存数据 | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T"></typeparam> | ||||
| 		/// <param name="key"></param> | ||||
| 		/// <returns></returns> | ||||
| 		Task<T> GetAsync<T>(string key); | ||||
| 		/// <summary> | ||||
| 		/// 循环或批量获取缓存数据 | ||||
| 		/// </summary> | ||||
| 		/// <param name="key"></param> | ||||
| 		/// <returns></returns> | ||||
| 		Task<string> GetAsync(string key); | ||||
| 		/// <summary> | ||||
| 		/// 循环或批量删除缓存键 | ||||
| 		/// </summary> | ||||
| 		/// <param name="keys">缓存键[数组]</param> | ||||
| 		Task RemoveAsync(params string[] keys); | ||||
| 		/// <summary> | ||||
| 		/// 缓存壳 | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T">缓存类型</typeparam> | ||||
| 		/// <param name="key">缓存键</param> | ||||
| 		/// <param name="timeoutSeconds">缓存秒数</param> | ||||
| 		/// <param name="getDataAsync">获取源数据的函数</param> | ||||
| 		/// <returns></returns> | ||||
| 		Task<T> ShellAsync<T>(string key, int timeoutSeconds, Func<Task<T>> getDataAsync); | ||||
| 		/// <summary> | ||||
| 		/// 缓存壳(哈希表) | ||||
| 		/// </summary> | ||||
| 		/// <typeparam name="T">缓存类型</typeparam> | ||||
| 		/// <param name="key">缓存键</param> | ||||
| 		/// <param name="field">字段</param> | ||||
| 		/// <param name="timeoutSeconds">缓存秒数</param> | ||||
| 		/// <param name="getDataAsync">获取源数据的函数</param> | ||||
| 		/// <returns></returns> | ||||
| 		Task<T> ShellAsync<T>(string key, string field, int timeoutSeconds, Func<Task<T>> getDataAsync); | ||||
| 	} | ||||
| } | ||||
| @@ -87,10 +87,6 @@ public interface IFreeSql : IDisposable { | ||||
| 	/// <param name="timeout">超时,未执行完将自动提交</param> | ||||
| 	void Transaction(Action handler, TimeSpan timeout); | ||||
|  | ||||
| 	/// <summary> | ||||
| 	/// 缓存 | ||||
| 	/// </summary> | ||||
| 	ICache Cache { get; } | ||||
| 	/// <summary> | ||||
| 	/// 数据库访问对象 | ||||
| 	/// </summary> | ||||
|   | ||||
| @@ -10,17 +10,17 @@ using System.Reflection; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FreeSql.Internal { | ||||
| 	internal abstract class CommonExpression { | ||||
| 	public abstract class CommonExpression { | ||||
|  | ||||
| 		internal CommonUtils _common; | ||||
| 		internal CommonProvider.AdoProvider _ado => _adoPriv ?? (_adoPriv = _common._orm.Ado as CommonProvider.AdoProvider); | ||||
| 		public CommonUtils _common; | ||||
| 		public CommonProvider.AdoProvider _ado => _adoPriv ?? (_adoPriv = _common._orm.Ado as CommonProvider.AdoProvider); | ||||
| 		CommonProvider.AdoProvider _adoPriv; | ||||
| 		internal CommonExpression(CommonUtils common) { | ||||
| 		public CommonExpression(CommonUtils common) { | ||||
| 			_common = common; | ||||
| 		} | ||||
|  | ||||
| 		static ConcurrentDictionary<Type, PropertyInfo[]> _dicReadAnonymousFieldDtoPropertys = new ConcurrentDictionary<Type, PropertyInfo[]>(); | ||||
| 		internal bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 		public 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) { | ||||
| 				case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString); | ||||
| @@ -180,7 +180,7 @@ namespace FreeSql.Internal { | ||||
| 			if (index >= 0) field.Append(" as").Append(++index); | ||||
| 			return false; | ||||
| 		} | ||||
| 		internal object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index, bool notRead) { | ||||
| 		public object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index, bool notRead) { | ||||
| 			if (parent.Childs.Any() == false) { | ||||
| 				if (notRead) { | ||||
| 					++index; | ||||
| @@ -215,7 +215,7 @@ namespace FreeSql.Internal { | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		internal ColumnInfo SearchColumnByField(List<SelectTableInfo> _tables, TableInfo currentTable, string field) { | ||||
| 		public ColumnInfo SearchColumnByField(List<SelectTableInfo> _tables, TableInfo currentTable, string field) { | ||||
| 			if (_tables != null) { | ||||
| 				var testCol = _common.TrimQuoteSqlName(field).Split(new[] { '.' }, 2); | ||||
| 				if (testCol.Length == 2) { | ||||
| @@ -232,11 +232,11 @@ namespace FreeSql.Internal { | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		internal string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 		public string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 			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) { | ||||
| 		public string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List<SelectTableInfo> _tables, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 			switch (exp?.NodeType) { | ||||
| 				case ExpressionType.Quote: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, getSelectGroupingMapString); | ||||
| 				case ExpressionType.Lambda: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as LambdaExpression)?.Body, isQuoteName, getSelectGroupingMapString); | ||||
| @@ -276,7 +276,7 @@ namespace FreeSql.Internal { | ||||
| 			{ ExpressionType.Modulo, "%" }, | ||||
| 			{ ExpressionType.Equal, "=" }, | ||||
| 		}; | ||||
| 		internal string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, TableInfo table, List<SelectColumnInfo> _selectColumnMap, Expression exp, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 		public string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, TableInfo table, List<SelectColumnInfo> _selectColumnMap, Expression exp, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 			var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = table }); | ||||
| 			if (exp.NodeType == ExpressionType.MemberAccess && exp.Type == typeof(bool)) | ||||
| 				return $"{sql} = {formatSql(true, null)}"; | ||||
| @@ -289,7 +289,7 @@ namespace FreeSql.Internal { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		internal string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 		public string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 			var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where }); | ||||
| 			if (exp.NodeType == ExpressionType.MemberAccess && exp.Type == typeof(bool)) | ||||
| 				return $"{sql} = {formatSql(true, null)}"; | ||||
| @@ -301,7 +301,7 @@ namespace FreeSql.Internal { | ||||
| 				default: return sql; | ||||
| 			} | ||||
| 		} | ||||
| 		internal void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 		public void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp, Func<Expression[], string> getSelectGroupingMapString) { | ||||
| 			var tbidx = _tables.Count; | ||||
| 			var filter = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where }); | ||||
| 			if (exp.NodeType == ExpressionType.MemberAccess && exp.Type == typeof(bool)) | ||||
| @@ -333,7 +333,7 @@ namespace FreeSql.Internal { | ||||
| 		internal static ConcurrentDictionary<Type, PropertyInfo> _dicNullableValueProperty = new ConcurrentDictionary<Type, PropertyInfo>(); | ||||
| 		static ConcurrentDictionary<Type, Expression> _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary<Type, Expression>(); | ||||
|  | ||||
| 		internal string ExpressionBinary(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc) { | ||||
| 		public string ExpressionBinary(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc) { | ||||
| 			switch (oper) { | ||||
| 				case "OR": | ||||
| 				case "|": | ||||
| @@ -399,7 +399,7 @@ namespace FreeSql.Internal { | ||||
| 			tsc.mapType = null; | ||||
| 			return $"{left} {oper} {right}"; | ||||
| 		} | ||||
| 		internal string ExpressionLambdaToSql(Expression exp, ExpTSC tsc) { | ||||
| 		public string ExpressionLambdaToSql(Expression exp, ExpTSC tsc) { | ||||
| 			if (exp == null) return ""; | ||||
| 			if (tsc.isDisableDiyParse == false && _common._orm.Aop.ParseExpression != null) { | ||||
| 				var args = new Aop.ParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(exp, tsc.CloneDisableDiyParse())); | ||||
| @@ -882,20 +882,20 @@ namespace FreeSql.Internal { | ||||
| 			return ExpressionBinary(tryoper, expBinary.Left, expBinary.Right, tsc); | ||||
| 		} | ||||
|  | ||||
| 		internal abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		internal abstract string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc); | ||||
| 		public abstract string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc); | ||||
|  | ||||
| 		internal enum ExpressionStyle { | ||||
| 		public enum ExpressionStyle { | ||||
| 			Where, AsSelect, SelectColumns | ||||
| 		} | ||||
| 		internal class ExpTSC { | ||||
| 		public class ExpTSC { | ||||
| 			public List<SelectTableInfo> _tables { get; set; } | ||||
| 			public List<SelectColumnInfo> _selectColumnMap { get; set; } | ||||
| 			public Func<Expression[], string> getSelectGroupingMapString { get; set; } | ||||
| @@ -932,7 +932,7 @@ namespace FreeSql.Internal { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		internal string formatSql(object obj, Type mapType) { | ||||
| 		public string formatSql(object obj, Type mapType) { | ||||
| 			return string.Concat(_ado.AddslashesProcessParam(obj, mapType)); | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using Microsoft.Extensions.Logging; | ||||
| using SafeObjectPool; | ||||
| using SafeObjectPool; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Concurrent; | ||||
| @@ -11,7 +10,7 @@ using System.Text; | ||||
| using System.Reflection; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
| 	abstract partial class AdoProvider : IAdo, IDisposable { | ||||
| 	public abstract partial class AdoProvider : IAdo, IDisposable { | ||||
|  | ||||
| 		protected abstract void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex); | ||||
| 		protected abstract DbCommand CreateCommand(); | ||||
| @@ -24,16 +23,12 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 		public ObjectPool<DbConnection> MasterPool { get; protected set; } | ||||
| 		public List<ObjectPool<DbConnection>> SlavePools { get; } = new List<ObjectPool<DbConnection>>(); | ||||
| 		public DataType DataType { get; } | ||||
| 		protected ICache _cache { get; set; } | ||||
| 		protected ILogger _log { get; set; } | ||||
| 		protected CommonUtils _util { get; set; } | ||||
| 		protected int slaveUnavailables = 0; | ||||
| 		private object slaveLock = new object(); | ||||
| 		private Random slaveRandom = new Random(); | ||||
|  | ||||
| 		public AdoProvider(ICache cache, ILogger log, DataType dataType) { | ||||
| 			this._cache = cache; | ||||
| 			this._log = log; | ||||
| 		public AdoProvider(DataType dataType) { | ||||
| 			this.DataType = dataType; | ||||
| 		} | ||||
|  | ||||
| @@ -43,7 +38,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			if (IsTracePerformance) { | ||||
| 				TimeSpan ts = DateTime.Now.Subtract(dt); | ||||
| 				if (e == null && ts.TotalMilliseconds > 100) | ||||
| 					_log.LogWarning(logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString()); | ||||
| 					Trace.WriteLine(logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString()); | ||||
| 				else | ||||
| 					logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)耗时{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString(); | ||||
| 			} | ||||
| @@ -59,7 +54,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 				log.Append(parm.ParameterName.PadRight(20, ' ')).Append(" = ").Append((parm.Value ?? DBNull.Value) == DBNull.Value ? "NULL" : parm.Value).Append("\r\n"); | ||||
|  | ||||
| 			log.Append(e.Message); | ||||
| 			_log.LogError(log.ToString()); | ||||
| 			Trace.WriteLine(log.ToString()); | ||||
|  | ||||
| 			if (cmd.Transaction != null) { | ||||
| 				var curTran = TransactionCurrentThread; | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Newtonsoft.Json; | ||||
| using SafeObjectPool; | ||||
| using SafeObjectPool; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Data.Common; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using System.Threading; | ||||
|  | ||||
| @@ -29,24 +28,6 @@ namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 		public DbTransaction TransactionCurrentThread => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.Transaction : null; | ||||
|  | ||||
| 		private Dictionary<int, List<string>> _preRemoveKeys = new Dictionary<int, List<string>>(); | ||||
| 		private object _preRemoveKeys_lock = new object(); | ||||
| 		public string[] PreRemove(params string[] key) { | ||||
| 			var tid = Thread.CurrentThread.ManagedThreadId; | ||||
| 			List<string> keys = null; | ||||
| 			if (key == null || key.Any() == false) return _preRemoveKeys.TryGetValue(tid, out keys) ? keys.ToArray() : new string[0]; | ||||
| 			_log.LogDebug($"线程{tid}事务预删除 {JsonConvert.SerializeObject(key)}"); | ||||
| 			if (_preRemoveKeys.TryGetValue(tid, out keys) == false) | ||||
| 				lock (_preRemoveKeys_lock) | ||||
| 					if (_preRemoveKeys.TryGetValue(tid, out keys) == false) { | ||||
| 						_preRemoveKeys.Add(tid, keys = new List<string>(key)); | ||||
| 						return key; | ||||
| 					} | ||||
| 			keys.AddRange(key); | ||||
| 			return keys.ToArray(); | ||||
| 		} | ||||
| 		public void TransactionPreRemoveCache(params string[] key) => PreRemove(key); | ||||
|  | ||||
| 		public void BeginTransaction(TimeSpan timeout) { | ||||
| 			if (TransactionCurrentThread != null) return; | ||||
|  | ||||
| @@ -58,7 +39,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 				conn = MasterPool.Get(); | ||||
| 				tran = new Transaction2(conn, conn.Value.BeginTransaction(), timeout); | ||||
| 			} catch(Exception ex) { | ||||
| 				_log.LogError($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}"); | ||||
| 				Trace.WriteLine($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}"); | ||||
| 				MasterPool.Return(conn); | ||||
| 				throw ex; | ||||
| 			} | ||||
| @@ -84,22 +65,15 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 					if (_trans.ContainsKey(tran.Conn.LastGetThreadId)) | ||||
| 						_trans.Remove(tran.Conn.LastGetThreadId); | ||||
|  | ||||
| 			var removeKeys = PreRemove(); | ||||
| 			if (_preRemoveKeys.ContainsKey(tran.Conn.LastGetThreadId)) | ||||
| 				lock (_preRemoveKeys_lock) | ||||
| 					if (_preRemoveKeys.ContainsKey(tran.Conn.LastGetThreadId)) | ||||
| 						_preRemoveKeys.Remove(tran.Conn.LastGetThreadId); | ||||
|  | ||||
| 			Exception ex = null; | ||||
| 			var f001 = isCommit ? "提交" : "回滚"; | ||||
| 			try { | ||||
| 				_log.LogDebug($"线程{tran.Conn.LastGetThreadId}事务{f001},批量删除缓存key {Newtonsoft.Json.JsonConvert.SerializeObject(removeKeys)}"); | ||||
| 				_cache.Remove(removeKeys); | ||||
| 				Trace.WriteLine($"线程{tran.Conn.LastGetThreadId}事务{f001}"); | ||||
| 				if (isCommit) tran.Transaction.Commit(); | ||||
| 				else tran.Transaction.Rollback(); | ||||
| 			} catch (Exception ex2) { | ||||
| 				ex = ex2; | ||||
| 				_log.LogError($"数据库出错({f001}事务):{ex.Message} {ex.StackTrace}"); | ||||
| 				Trace.WriteLine($"数据库出错({f001}事务):{ex.Message} {ex.StackTrace}"); | ||||
| 			} finally { | ||||
| 				ReturnConnection(MasterPool, tran.Conn, ex); //MasterPool.Return(tran.Conn, ex); | ||||
| 			} | ||||
|   | ||||
| @@ -5,7 +5,7 @@ using System.Linq.Expressions; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
| 	class AopProvider : IAop { | ||||
| 	public class AopProvider : IAop { | ||||
| 		public EventHandler<Aop.ToListEventArgs> ToList { get; set; } | ||||
| 		public EventHandler<Aop.WhereEventArgs> Where { get; set; } | ||||
| 		public EventHandler<Aop.ParseExpressionEventArgs> ParseExpression { get; set; } | ||||
|   | ||||
| @@ -1,186 +0,0 @@ | ||||
| using Microsoft.Extensions.Caching.Distributed; | ||||
| using Microsoft.Extensions.Caching.Memory; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
| using Newtonsoft.Json; | ||||
| using System; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
| 	class CacheProvider : ICache, IDisposable { | ||||
|  | ||||
| 		public IDistributedCache Cache { get; private set; } | ||||
| 		private bool CacheSupportMultiRemove = false; | ||||
| 		private static DateTime dt1970 = new DateTime(1970, 1, 1); | ||||
|  | ||||
| 		public CacheProvider(IDistributedCache cache, ILogger log) { | ||||
| 			if (cache == null) cache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions { })); | ||||
| 			Cache = cache; | ||||
| 			var key1 = $"testCacheSupportMultiRemoveFreeSql{Guid.NewGuid().ToString("N")}"; | ||||
| 			var key2 = $"testCacheSupportMultiRemoveFreeSql{Guid.NewGuid().ToString("N")}"; | ||||
| 			Cache.Set(key1, new byte[] { 65 }); | ||||
| 			Cache.Set(key2, new byte[] { 65 }); | ||||
| 			try { Cache.Remove($"{key1}|{key2}"); } catch { } // redis-cluster 不允许执行 multi keys 命令 | ||||
| 			CacheSupportMultiRemove = Cache.Get(key1) == null && cache.Get(key2) == null; | ||||
| 			if (CacheSupportMultiRemove == false) { | ||||
| 				//log.LogWarning("FreeSql Warning: 低性能, IDistributedCache 没实现批量删除缓存 Cache.Remove(\"key1|key2\")."); | ||||
| 				Remove(key1, key2); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		~CacheProvider() { | ||||
| 			this.Dispose(); | ||||
| 		} | ||||
| 		bool _isdisposed = false; | ||||
| 		public void Dispose() { | ||||
| 			if (_isdisposed) return; | ||||
|  | ||||
| 			Cache = null; | ||||
| 		} | ||||
|  | ||||
| 		public Func<object, string> Serialize { get; set; } | ||||
| 		public Func<string, Type, object> Deserialize { get; set; } | ||||
|  | ||||
| 		Func<JsonSerializerSettings> JsonSerializerSettings = () => { | ||||
| 			var st = new JsonSerializerSettings(); | ||||
| 			st.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); | ||||
| 			st.DateFormatHandling = DateFormatHandling.IsoDateFormat; | ||||
| 			st.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; | ||||
| 			return st; | ||||
| 		}; | ||||
| 		string SerializeObject(object value) { | ||||
| 			if (Serialize != null) return Serialize(value); | ||||
| 			return JsonConvert.SerializeObject(value, this.JsonSerializerSettings()); | ||||
| 		} | ||||
| 		T DeserializeObject<T>(string value) { | ||||
| 			if (Deserialize != null) return (T) Deserialize(value, typeof(T)); | ||||
| 			return JsonConvert.DeserializeObject<T>(value, this.JsonSerializerSettings()); | ||||
| 		} | ||||
|  | ||||
| 		public void Set<T>(string key, T data, int timeoutSeconds = 0) { | ||||
| 			if (string.IsNullOrEmpty(key)) return; | ||||
| 			Cache.Set(key, Encoding.UTF8.GetBytes(this.SerializeObject(data)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) }); | ||||
| 		} | ||||
| 		public T Get<T>(string key) { | ||||
| 			if (string.IsNullOrEmpty(key)) return default(T); | ||||
| 			var value = Cache.Get(key); | ||||
| 			if (value == null) return default(T); | ||||
| 			return this.DeserializeObject<T>(Encoding.UTF8.GetString(value)); | ||||
| 		} | ||||
| 		public string Get(string key) { | ||||
| 			if (string.IsNullOrEmpty(key)) return null; | ||||
| 			var value = Cache.Get(key); | ||||
| 			if (value == null) return null; | ||||
| 			return Encoding.UTF8.GetString(value); | ||||
| 		} | ||||
|  | ||||
| 		async public Task SetAsync<T>(string key, T data, int timeoutSeconds = 0) { | ||||
| 			if (string.IsNullOrEmpty(key)) return; | ||||
| 			await Cache.SetAsync(key, Encoding.UTF8.GetBytes(this.SerializeObject(data)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) }); | ||||
| 		} | ||||
| 		async public Task<T> GetAsync<T>(string key) { | ||||
| 			if (string.IsNullOrEmpty(key)) return default(T); | ||||
| 			var value = await Cache.GetAsync(key); | ||||
| 			if (value == null) return default(T); | ||||
| 			return this.DeserializeObject<T>(Encoding.UTF8.GetString(value)); | ||||
| 		} | ||||
| 		async public Task<string> GetAsync(string key) { | ||||
| 			if (string.IsNullOrEmpty(key)) return null; | ||||
| 			var value = await Cache.GetAsync(key); | ||||
| 			if (value == null) return null; | ||||
| 			return Encoding.UTF8.GetString(value); | ||||
| 		} | ||||
|  | ||||
| 		public void Remove(params string[] keys) { | ||||
| 			if (keys == null || keys.Length == 0) return; | ||||
| 			var keysDistinct = keys.Distinct(); | ||||
| 			if (CacheSupportMultiRemove) Cache.Remove(string.Join("|", keysDistinct)); | ||||
| 			else foreach (var key in keysDistinct) Cache.Remove(key); | ||||
| 		} | ||||
|  | ||||
| 		async public Task RemoveAsync(params string[] keys) { | ||||
| 			if (keys == null || keys.Length == 0) return; | ||||
| 			var keysDistinct = keys.Distinct(); | ||||
| 			if (CacheSupportMultiRemove) await Cache.RemoveAsync(string.Join("|", keysDistinct)); | ||||
| 			else foreach (var key in keysDistinct) await Cache.RemoveAsync(key); | ||||
| 		} | ||||
|  | ||||
| 		public T Shell<T>(string key, int timeoutSeconds, Func<T> getData) { | ||||
| 			if (timeoutSeconds <= 0) return getData(); | ||||
| 			if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null"); | ||||
| 			var cacheValue = Cache.Get(key); | ||||
| 			if (cacheValue != null) { | ||||
| 				try { | ||||
| 					var txt = Encoding.UTF8.GetString(cacheValue); | ||||
| 					return DeserializeObject<T>(txt); | ||||
| 				} catch { | ||||
| 					Cache.Remove(key); | ||||
| 					throw; | ||||
| 				} | ||||
| 			} | ||||
| 			var ret = getData(); | ||||
| 			Cache.Set(key, Encoding.UTF8.GetBytes(SerializeObject(ret)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) }); | ||||
| 			return ret; | ||||
| 		} | ||||
|  | ||||
| 		public T Shell<T>(string key, string field, int timeoutSeconds, Func<T> getData) { | ||||
| 			if (timeoutSeconds <= 0) return getData(); | ||||
| 			if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null"); | ||||
| 			var hashkey = $"{key}:{field}"; | ||||
| 			var cacheValue = Cache.Get(hashkey); | ||||
| 			if (cacheValue != null) { | ||||
| 				try { | ||||
| 					var txt = Encoding.UTF8.GetString(cacheValue); | ||||
| 					var value = DeserializeObject<(T, long)>(txt); | ||||
| 					if (DateTime.Now.Subtract(dt1970.AddSeconds(value.Item2)).TotalSeconds <= timeoutSeconds) return value.Item1; | ||||
| 				} catch { | ||||
| 					Cache.Remove(hashkey); | ||||
| 					throw; | ||||
| 				} | ||||
| 			} | ||||
| 			var ret = (getData(), (long) DateTime.Now.Subtract(dt1970).TotalSeconds); | ||||
| 			Cache.Set(hashkey, Encoding.UTF8.GetBytes(SerializeObject(ret))); | ||||
| 			return ret.Item1; | ||||
| 		} | ||||
|  | ||||
| 		async public Task<T> ShellAsync<T>(string key, int timeoutSeconds, Func<Task<T>> getDataAsync) { | ||||
| 			if (timeoutSeconds <= 0) return await getDataAsync(); | ||||
| 			if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null"); | ||||
| 			var cacheValue = await Cache.GetAsync(key); | ||||
| 			if (cacheValue != null) { | ||||
| 				try { | ||||
| 					var txt = Encoding.UTF8.GetString(cacheValue); | ||||
| 					return DeserializeObject<T>(txt); | ||||
| 				} catch { | ||||
| 					await Cache.RemoveAsync(key); | ||||
| 					throw; | ||||
| 				} | ||||
| 			} | ||||
| 			var ret = await getDataAsync(); | ||||
| 			await Cache.SetAsync(key, Encoding.UTF8.GetBytes(SerializeObject(ret)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) }); | ||||
| 			return ret; | ||||
| 		} | ||||
|  | ||||
| 		async public Task<T> ShellAsync<T>(string key, string field, int timeoutSeconds, Func<Task<T>> getDataAsync) { | ||||
| 			if (timeoutSeconds <= 0) return await getDataAsync(); | ||||
| 			if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null"); | ||||
| 			var hashkey = $"{key}:{field}"; | ||||
| 			var cacheValue = await Cache.GetAsync(hashkey); | ||||
| 			if (cacheValue != null) { | ||||
| 				try { | ||||
| 					var txt = Encoding.UTF8.GetString(cacheValue); | ||||
| 					var value = DeserializeObject<(T, long)>(txt); | ||||
| 					if (DateTime.Now.Subtract(dt1970.AddSeconds(value.Item2)).TotalSeconds <= timeoutSeconds) return value.Item1; | ||||
| 				} catch { | ||||
| 					await Cache.RemoveAsync(hashkey); | ||||
| 					throw; | ||||
| 				} | ||||
| 			} | ||||
| 			var ret = (await getDataAsync(), (long) DateTime.Now.Subtract(dt1970).TotalSeconds); | ||||
| 			await Cache.SetAsync(hashkey, Encoding.UTF8.GetBytes(SerializeObject(ret))); | ||||
| 			return ret.Item1; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -9,7 +9,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract partial class DeleteProvider<T1> : IDelete<T1> where T1 : class { | ||||
| 	public abstract partial class DeleteProvider<T1> : IDelete<T1> where T1 : class { | ||||
| 		protected IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
|   | ||||
| @@ -11,7 +11,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract partial class InsertProvider<T1> : IInsert<T1> where T1 : class { | ||||
| 	public abstract partial class InsertProvider<T1> : IInsert<T1> where T1 : class { | ||||
| 		protected IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| @@ -69,7 +69,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 		} | ||||
|  | ||||
| 		#region 参数化数据限制,或values数量限制 | ||||
| 		internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit) { | ||||
| 		protected List<T1>[] SplitSource(int valuesLimit, int parameterLimit) { | ||||
| 			valuesLimit = valuesLimit - 1; | ||||
| 			parameterLimit = parameterLimit - 1; | ||||
| 			if (_source == null || _source.Any() == false) return new List<T1>[0]; | ||||
| @@ -101,7 +101,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 				return ret; | ||||
| 			} | ||||
| 		} | ||||
| 		internal int SplitExecuteAffrows(int valuesLimit, int parameterLimit) { | ||||
| 		protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = 0; | ||||
| 			if (ss.Any() == false) { | ||||
| @@ -137,7 +137,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) { | ||||
| 		async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = 0; | ||||
| 			if (ss.Any() == false) { | ||||
| @@ -173,7 +173,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		internal long SplitExecuteIdentity(int valuesLimit, int parameterLimit) { | ||||
| 		protected long SplitExecuteIdentity(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			long ret = 0; | ||||
| 			if (ss.Any() == false) { | ||||
| @@ -211,7 +211,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit) { | ||||
| 		async protected Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			long ret = 0; | ||||
| 			if (ss.Any() == false) { | ||||
| @@ -249,7 +249,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		internal List<T1> SplitExecuteInserted(int valuesLimit, int parameterLimit) { | ||||
| 		protected List<T1> SplitExecuteInserted(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = new List<T1>(); | ||||
| 			if (ss.Any() == false) { | ||||
| @@ -285,7 +285,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit) { | ||||
| 		async protected Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = new List<T1>(); | ||||
| 			if (ss.Any() == false) { | ||||
| @@ -323,7 +323,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 		} | ||||
| 		#endregion | ||||
|  | ||||
| 		internal int RawExecuteAffrows() { | ||||
| 		protected int RawExecuteAffrows() { | ||||
| 			var sql = ToSql(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| @@ -341,7 +341,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			this.ClearData(); | ||||
| 			return affrows; | ||||
| 		} | ||||
| 		async internal Task<int> RawExecuteAffrowsAsync() { | ||||
| 		async protected Task<int> RawExecuteAffrowsAsync() { | ||||
| 			var sql = ToSql(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| @@ -359,10 +359,10 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			this.ClearData(); | ||||
| 			return affrows; | ||||
| 		} | ||||
| 		internal abstract long RawExecuteIdentity(); | ||||
| 		internal abstract Task<long> RawExecuteIdentityAsync(); | ||||
| 		internal abstract List<T1> RawExecuteInserted(); | ||||
| 		internal abstract Task<List<T1>> RawExecuteInsertedAsync(); | ||||
| 		protected abstract long RawExecuteIdentity(); | ||||
| 		protected abstract Task<long> RawExecuteIdentityAsync(); | ||||
| 		protected abstract List<T1> RawExecuteInserted(); | ||||
| 		protected abstract Task<List<T1>> RawExecuteInsertedAsync(); | ||||
|  | ||||
| 		public abstract int ExecuteAffrows(); | ||||
| 		public abstract Task<int> ExecuteAffrowsAsync(); | ||||
|   | ||||
| @@ -14,16 +14,15 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select0Provider<TSelect, T1> : ISelect0<TSelect, T1> where TSelect : class where T1 : class { | ||||
| 	public abstract class Select0Provider<TSelect, T1> : ISelect0<TSelect, T1> where TSelect : class where T1 : class { | ||||
|  | ||||
| 		protected int _limit, _skip; | ||||
| 		protected string _select = "SELECT ", _orderby, _groupby, _having; | ||||
| 		protected StringBuilder _where = new StringBuilder(); | ||||
| 		protected List<DbParameter> _params = new List<DbParameter>(); | ||||
| 		internal List<SelectTableInfo> _tables = new List<SelectTableInfo>(); | ||||
| 		protected List<SelectTableInfo> _tables = new List<SelectTableInfo>(); | ||||
| 		protected List<Func<Type, string, string>> _tableRules = new List<Func<Type, string, string>>(); | ||||
| 		protected StringBuilder _join = new StringBuilder(); | ||||
| 		protected (int seconds, string key) _cache = (0, null); | ||||
| 		protected IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| @@ -34,7 +33,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 		protected bool _distinct; | ||||
| 		protected Expression _selectExpression; | ||||
|  | ||||
| 		internal static void CopyData(Select0Provider<TSelect, T1> from, object to, ReadOnlyCollection<ParameterExpression> lambParms) { | ||||
| 		public static void CopyData(Select0Provider<TSelect, T1> from, object to, ReadOnlyCollection<ParameterExpression> lambParms) { | ||||
| 			var toType = to?.GetType(); | ||||
| 			if (toType == null) return; | ||||
| 			toType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._limit); | ||||
| @@ -63,7 +62,6 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			} | ||||
| 			toType.GetField("_tableRules", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._tableRules); | ||||
| 			toType.GetField("_join", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._join.ToString())); | ||||
| 			toType.GetField("_cache", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._cache); | ||||
| 			//toType.GetField("_orm", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._orm); | ||||
| 			//toType.GetField("_commonUtils", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonUtils); | ||||
| 			//toType.GetField("_commonExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonExpression); | ||||
| @@ -109,10 +107,6 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			return (await this.ToListAsync<int>("1")).FirstOrDefault() == 1; | ||||
| 		} | ||||
|  | ||||
| 		public TSelect Caching(int seconds, string key = null) { | ||||
| 			_cache = (seconds, key); | ||||
| 			return this as TSelect; | ||||
| 		} | ||||
| 		public long Count() => this.ToList<int>("count(1)").FirstOrDefault(); | ||||
| 		async public Task<long> CountAsync() => (await this.ToListAsync<int>("count(1)")).FirstOrDefault(); | ||||
|  | ||||
| @@ -220,166 +214,142 @@ namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 		public DataTable ToDataTable(string field = null) { | ||||
| 			var sql = this.ToSql(field); | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql; | ||||
|  | ||||
| 			return _orm.Cache.Shell(_cache.key, _cache.seconds, () => { | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				DataTable ret = null; | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					ret = _orm.Ado.ExecuteDataTable(_connection, _transaction, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			DataTable ret = null; | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				ret = _orm.Ado.ExecuteDataTable(_connection, _transaction, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			return ret; | ||||
| 		} | ||||
| 		public Task<DataTable> ToDataTableAsync(string field = null) { | ||||
| 		async public Task<DataTable> ToDataTableAsync(string field = null) { | ||||
| 			var sql = this.ToSql(field); | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql; | ||||
|  | ||||
| 			return _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => { | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				DataTable ret = null; | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					ret = await _orm.Ado.ExecuteDataTableAsync(_connection, _transaction, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			DataTable ret = null; | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				ret = await _orm.Ado.ExecuteDataTableAsync(_connection, _transaction, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			return ret; | ||||
| 		} | ||||
|  | ||||
| 		public List<TTuple> ToList<TTuple>(string field) { | ||||
| 			var sql = this.ToSql(field); | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql; | ||||
|  | ||||
| 			return _orm.Cache.Shell(_cache.key, _cache.seconds, () => { | ||||
| 				var type = typeof(TTuple); | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				var ret = new List<TTuple>(); | ||||
| 				var flagStr = $"ToListField:{field}"; | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					_orm.Ado.ExecuteReader(_connection, _transaction, dr => { | ||||
| 						var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils); | ||||
| 						ret.Add((TTuple)read.Value); | ||||
| 					}, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var type = typeof(TTuple); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			var ret = new List<TTuple>(); | ||||
| 			var flagStr = $"ToListField:{field}"; | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				_orm.Ado.ExecuteReader(_connection, _transaction, dr => { | ||||
| 					var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils); | ||||
| 					ret.Add((TTuple)read.Value); | ||||
| 				}, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			return ret; | ||||
| 		} | ||||
| 		public Task<List<TTuple>> ToListAsync<TTuple>(string field) { | ||||
| 		async public Task<List<TTuple>> ToListAsync<TTuple>(string field) { | ||||
| 			var sql = this.ToSql(field); | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql; | ||||
|  | ||||
| 			return _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => { | ||||
| 				var type = typeof(TTuple); | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				var ret = new List<TTuple>(); | ||||
| 				var flagStr = $"ToListField:{field}"; | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => { | ||||
| 						var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils); | ||||
| 						ret.Add((TTuple)read.Value); | ||||
| 						return Task.CompletedTask; | ||||
| 					}, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var type = typeof(TTuple); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			var ret = new List<TTuple>(); | ||||
| 			var flagStr = $"ToListField:{field}"; | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => { | ||||
| 					var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils); | ||||
| 					ret.Add((TTuple)read.Value); | ||||
| 					return Task.CompletedTask; | ||||
| 				}, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			return ret; | ||||
| 		} | ||||
| 		internal List<T1> ToListAfPrivate(string sql, GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) { | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}"; | ||||
|  | ||||
| 			return _orm.Cache.Shell(_cache.key, _cache.seconds, () => { | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				var ret = new List<T1>(); | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					_orm.Ado.ExecuteReader(_connection, _transaction, dr => { | ||||
| 						ret.Add(af.Read(_orm, dr)); | ||||
| 						if (otherData != null) { | ||||
| 							var idx = af.FieldCount - 1; | ||||
| 							foreach (var other in otherData) | ||||
| 								other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false)); | ||||
| 						} | ||||
| 					}, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret); | ||||
| 				_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 				_trackToList?.Invoke(ret); | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			var ret = new List<T1>(); | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				_orm.Ado.ExecuteReader(_connection, _transaction, dr => { | ||||
| 					ret.Add(af.Read(_orm, dr)); | ||||
| 					if (otherData != null) { | ||||
| 						var idx = af.FieldCount - 1; | ||||
| 						foreach (var other in otherData) | ||||
| 							other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false)); | ||||
| 					} | ||||
| 				}, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret); | ||||
| 			_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 			_trackToList?.Invoke(ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal Task<List<T1>> ToListAfPrivateAsync(string sql, GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) { | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}"; | ||||
|  | ||||
| 			return await _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => { | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				var ret = new List<T1>(); | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => { | ||||
| 						ret.Add(af.Read(_orm, dr)); | ||||
| 						if (otherData != null) { | ||||
| 							var idx = af.FieldCount - 1; | ||||
| 							foreach (var other in otherData) | ||||
| 								other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false)); | ||||
| 						} | ||||
| 						return Task.CompletedTask; | ||||
| 					}, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret); | ||||
| 				_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 				_trackToList?.Invoke(ret); | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			var ret = new List<T1>(); | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => { | ||||
| 					ret.Add(af.Read(_orm, dr)); | ||||
| 					if (otherData != null) { | ||||
| 						var idx = af.FieldCount - 1; | ||||
| 						foreach (var other in otherData) | ||||
| 							other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false)); | ||||
| 					} | ||||
| 					return Task.CompletedTask; | ||||
| 				}, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret); | ||||
| 			_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 			_trackToList?.Invoke(ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		internal List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) { | ||||
| 			string sql = null; | ||||
| @@ -427,60 +397,52 @@ namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 		protected List<TReturn> ToListMapReader<TReturn>((ReadAnonymousTypeInfo map, string field) af) { | ||||
| 			var sql = this.ToSql(af.field); | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}"; | ||||
|  | ||||
| 			return _orm.Cache.Shell(_cache.key, _cache.seconds, () => { | ||||
| 				var type = typeof(TReturn); | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				var ret = new List<TReturn>(); | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					_orm.Ado.ExecuteReader(_connection, _transaction, dr => { | ||||
| 						var index = -1; | ||||
| 						ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false)); | ||||
| 					}, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 				_trackToList?.Invoke(ret); | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var type = typeof(TReturn); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			var ret = new List<TReturn>(); | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				_orm.Ado.ExecuteReader(_connection, _transaction, dr => { | ||||
| 					var index = -1; | ||||
| 					ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false)); | ||||
| 				}, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 			_trackToList?.Invoke(ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async protected Task<List<TReturn>> ToListMapReaderAsync<TReturn>((ReadAnonymousTypeInfo map, string field) af) { | ||||
| 			var sql = this.ToSql(af.field); | ||||
| 			if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}"; | ||||
|  | ||||
| 			return await _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => { | ||||
| 				var type = typeof(TReturn); | ||||
| 				var dbParms = _params.ToArray(); | ||||
| 				var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 				_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 				var ret = new List<TReturn>(); | ||||
| 				Exception exception = null; | ||||
| 				try { | ||||
| 					await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => { | ||||
| 						var index = -1; | ||||
| 						ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false)); | ||||
| 						return Task.CompletedTask; | ||||
| 					}, CommandType.Text, sql, dbParms); | ||||
| 				} catch (Exception ex) { | ||||
| 					exception = ex; | ||||
| 					throw ex; | ||||
| 				} finally { | ||||
| 					var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 					_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 				} | ||||
| 				_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 				_trackToList?.Invoke(ret); | ||||
| 				return ret; | ||||
| 			}); | ||||
| 			var type = typeof(TReturn); | ||||
| 			var dbParms = _params.ToArray(); | ||||
| 			var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms); | ||||
| 			_orm.Aop.CurdBefore?.Invoke(this, before); | ||||
| 			var ret = new List<TReturn>(); | ||||
| 			Exception exception = null; | ||||
| 			try { | ||||
| 				await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => { | ||||
| 					var index = -1; | ||||
| 					ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false)); | ||||
| 					return Task.CompletedTask; | ||||
| 				}, CommandType.Text, sql, dbParms); | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.CurdAfterEventArgs(before, exception, ret); | ||||
| 				_orm.Aop.CurdAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 			_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret)); | ||||
| 			_trackToList?.Invoke(ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		protected (ReadAnonymousTypeInfo map, string field) GetExpressionField(Expression newexp) { | ||||
| 			var map = new ReadAnonymousTypeInfo(); | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> | ||||
| 	public abstract class Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class | ||||
|   | ||||
| @@ -16,7 +16,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select1Provider<T1> : Select0Provider<ISelect<T1>, T1>, ISelect<T1> | ||||
| 	public abstract class Select1Provider<T1> : Select0Provider<ISelect<T1>, T1>, ISelect<T1> | ||||
| 			where T1 : class { | ||||
| 		public Select1Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select2Provider<T1, T2> : Select0Provider<ISelect<T1, T2>, T1>, ISelect<T1, T2> | ||||
| 	public abstract class Select2Provider<T1, T2> : Select0Provider<ISelect<T1, T2>, T1>, ISelect<T1, T2> | ||||
| 			where T1 : class | ||||
| 			where T2 : class { | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select3Provider<T1, T2, T3> : Select0Provider<ISelect<T1, T2, T3>, T1>, ISelect<T1, T2, T3> | ||||
| 	public abstract class Select3Provider<T1, T2, T3> : Select0Provider<ISelect<T1, T2, T3>, T1>, ISelect<T1, T2, T3> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class { | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select4Provider<T1, T2, T3, T4> : Select0Provider<ISelect<T1, T2, T3, T4>, T1>, ISelect<T1, T2, T3, T4> | ||||
| 	public abstract class Select4Provider<T1, T2, T3, T4> : Select0Provider<ISelect<T1, T2, T3, T4>, T1>, ISelect<T1, T2, T3, T4> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select5Provider<T1, T2, T3, T4, T5> : Select0Provider<ISelect<T1, T2, T3, T4, T5>, T1>, ISelect<T1, T2, T3, T4, T5> | ||||
| 	public abstract class Select5Provider<T1, T2, T3, T4, T5> : Select0Provider<ISelect<T1, T2, T3, T4, T5>, T1>, ISelect<T1, T2, T3, T4, T5> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select6Provider<T1, T2, T3, T4, T5, T6> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6>, T1>, ISelect<T1, T2, T3, T4, T5, T6> | ||||
| 	public abstract class Select6Provider<T1, T2, T3, T4, T5, T6> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6>, T1>, ISelect<T1, T2, T3, T4, T5, T6> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select7Provider<T1, T2, T3, T4, T5, T6, T7> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7> | ||||
| 	public abstract class Select7Provider<T1, T2, T3, T4, T5, T6, T7> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8> | ||||
| 	public abstract class Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class | ||||
|   | ||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract class Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> | ||||
| 	public abstract class Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> | ||||
| 			where T1 : class | ||||
| 			where T2 : class | ||||
| 			where T3 : class | ||||
|   | ||||
| @@ -8,7 +8,7 @@ using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
| 	class SelectGroupingProvider<TKey, TValue> : ISelectGrouping<TKey, TValue> { | ||||
| 	public class SelectGroupingProvider<TKey, TValue> : ISelectGrouping<TKey, TValue> { | ||||
|  | ||||
| 		internal object _select; | ||||
| 		internal ReadAnonymousTypeInfo _map; | ||||
|   | ||||
| @@ -11,7 +11,7 @@ using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	abstract partial class UpdateProvider<T1> : IUpdate<T1> where T1 : class { | ||||
| 	public abstract partial class UpdateProvider<T1> : IUpdate<T1> where T1 : class { | ||||
| 		protected IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| @@ -106,7 +106,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 				return ret; | ||||
| 			} | ||||
| 		} | ||||
| 		internal int SplitExecuteAffrows(int valuesLimit, int parameterLimit) { | ||||
| 		protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = 0; | ||||
| 			if (ss.Length <= 1) { | ||||
| @@ -138,7 +138,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) { | ||||
| 		async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = 0; | ||||
| 			if (ss.Length <= 1) { | ||||
| @@ -170,7 +170,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		internal List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit) { | ||||
| 		protected List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = new List<T1>(); | ||||
| 			if (ss.Length <= 1) { | ||||
| @@ -202,7 +202,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit) { | ||||
| 		async protected Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit) { | ||||
| 			var ss = SplitSource(valuesLimit, parameterLimit); | ||||
| 			var ret = new List<T1>(); | ||||
| 			if (ss.Length <= 1) { | ||||
| @@ -236,7 +236,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 		} | ||||
| 		#endregion | ||||
|  | ||||
| 		internal int RawExecuteAffrows() { | ||||
| 		protected int RawExecuteAffrows() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 			var dbParms = _params.Concat(_paramsSource).ToArray(); | ||||
| @@ -257,7 +257,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			this.ClearData(); | ||||
| 			return affrows; | ||||
| 		} | ||||
| 		async internal Task<int> RawExecuteAffrowsAsync() { | ||||
| 		async protected Task<int> RawExecuteAffrowsAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 			var dbParms = _params.Concat(_paramsSource).ToArray(); | ||||
| @@ -278,8 +278,8 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			this.ClearData(); | ||||
| 			return affrows; | ||||
| 		} | ||||
| 		internal abstract List<T1> RawExecuteUpdated(); | ||||
| 		internal abstract Task<List<T1>> RawExecuteUpdatedAsync(); | ||||
| 		protected abstract List<T1> RawExecuteUpdated(); | ||||
| 		protected abstract Task<List<T1>> RawExecuteUpdatedAsync(); | ||||
|  | ||||
| 		public abstract int ExecuteAffrows(); | ||||
| 		public abstract Task<int> ExecuteAffrowsAsync(); | ||||
|   | ||||
| @@ -2,43 +2,46 @@ | ||||
| using FreeSql.DatabaseModel; | ||||
| using FreeSql.Extensions.EntityUtil; | ||||
| using FreeSql.Internal.Model; | ||||
| using SafeObjectPool; | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | ||||
| using System.Data.Common; | ||||
| using System.Linq; | ||||
| using System.Linq.Expressions; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal { | ||||
| 	internal abstract class CommonUtils { | ||||
| 	public abstract class CommonUtils { | ||||
|  | ||||
| 		internal abstract string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value); | ||||
| 		internal abstract DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value); | ||||
| 		internal abstract DbParameter[] GetDbParamtersByObject(string sql, object obj); | ||||
| 		internal abstract string FormatSql(string sql, params object[] args); | ||||
| 		internal abstract string QuoteSqlName(string name); | ||||
| 		internal abstract string TrimQuoteSqlName(string name); | ||||
| 		internal abstract string QuoteParamterName(string name); | ||||
| 		internal abstract string IsNull(string sql, object value); | ||||
| 		internal abstract string StringConcat(string[] objs, Type[] types); | ||||
| 		internal abstract string Mod(string left, string right, Type leftType, Type rightType); | ||||
| 		internal abstract string QuoteWriteParamter(Type type, string paramterName); | ||||
| 		internal abstract string QuoteReadColumn(Type type, string columnName); | ||||
| 		public abstract string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value); | ||||
| 		public abstract DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value); | ||||
| 		public abstract DbParameter[] GetDbParamtersByObject(string sql, object obj); | ||||
| 		public abstract string FormatSql(string sql, params object[] args); | ||||
| 		public abstract string QuoteSqlName(string name); | ||||
| 		public abstract string TrimQuoteSqlName(string name); | ||||
| 		public abstract string QuoteParamterName(string name); | ||||
| 		public abstract string IsNull(string sql, object value); | ||||
| 		public abstract string StringConcat(string[] objs, Type[] types); | ||||
| 		public abstract string Mod(string left, string right, Type leftType, Type rightType); | ||||
| 		public abstract string QuoteWriteParamter(Type type, string paramterName); | ||||
| 		public abstract string QuoteReadColumn(Type type, string columnName); | ||||
|  | ||||
| 		internal IFreeSql _orm { get; set; } | ||||
| 		internal ICodeFirst CodeFirst => _orm.CodeFirst; | ||||
| 		internal TableInfo GetTableByEntity(Type entity) => Utils.GetTableByEntity(entity, this); | ||||
| 		internal List<DbTableInfo> dbTables { get; set; } | ||||
| 		internal object dbTablesLock = new object(); | ||||
| 		public IFreeSql _orm { get; set; } | ||||
| 		public ICodeFirst CodeFirst => _orm.CodeFirst; | ||||
| 		public TableInfo GetTableByEntity(Type entity) => Utils.GetTableByEntity(entity, this); | ||||
| 		public List<DbTableInfo> dbTables { get; set; } | ||||
| 		public object dbTablesLock = new object(); | ||||
|  | ||||
| 		public CommonUtils(IFreeSql orm) { | ||||
| 			_orm = orm; | ||||
| 		} | ||||
|  | ||||
| 		ConcurrentDictionary<Type, TableAttribute> dicConfigEntity = new ConcurrentDictionary<Type, TableAttribute>(); | ||||
| 		internal ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) { | ||||
| 		public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) { | ||||
| 			if (entity == null) return _orm.CodeFirst; | ||||
| 			var type = typeof(T); | ||||
| 			var table = dicConfigEntity.GetOrAdd(type, new TableAttribute()); | ||||
| @@ -47,7 +50,7 @@ namespace FreeSql.Internal { | ||||
| 			Utils.RemoveTableByEntity(type, this); //remove cache | ||||
| 			return _orm.CodeFirst; | ||||
| 		} | ||||
| 		internal ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) { | ||||
| 		public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) { | ||||
| 			if (entity == null) return _orm.CodeFirst; | ||||
| 			var table = dicConfigEntity.GetOrAdd(type, new TableAttribute()); | ||||
| 			var fluent = new TableFluent(type, table); | ||||
| @@ -55,10 +58,10 @@ namespace FreeSql.Internal { | ||||
| 			Utils.RemoveTableByEntity(type, this); //remove cache | ||||
| 			return _orm.CodeFirst; | ||||
| 		} | ||||
| 		internal TableAttribute GetConfigEntity(Type type) { | ||||
| 		public TableAttribute GetConfigEntity(Type type) { | ||||
| 			return dicConfigEntity.TryGetValue(type, out var trytb) ? trytb : null; | ||||
| 		} | ||||
| 		internal TableAttribute GetEntityTableAttribute(Type type) { | ||||
| 		public TableAttribute GetEntityTableAttribute(Type type) { | ||||
| 			TableAttribute attr = null; | ||||
| 			if (_orm.Aop.ConfigEntity != null) { | ||||
| 				var aope = new Aop.ConfigEntityEventArgs(type); | ||||
| @@ -84,7 +87,7 @@ namespace FreeSql.Internal { | ||||
| 			if (!string.IsNullOrEmpty(attr.SelectFilter)) return attr; | ||||
| 			return null; | ||||
| 		} | ||||
| 		internal ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto) { | ||||
| 		public ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto) { | ||||
| 			ColumnAttribute attr = null; | ||||
| 			if (_orm.Aop.ConfigEntityProperty != null) { | ||||
| 				var aope = new Aop.ConfigEntityPropertyEventArgs(type, proto); | ||||
| @@ -137,7 +140,7 @@ namespace FreeSql.Internal { | ||||
| 			return ret; | ||||
| 		} | ||||
|  | ||||
| 		internal string WhereObject(TableInfo table, string aliasAndDot, object dywhere) { | ||||
| 		public string WhereObject(TableInfo table, string aliasAndDot, object dywhere) { | ||||
| 			if (dywhere == null) return ""; | ||||
| 			var type = dywhere.GetType(); | ||||
| 			var primarys = table.Primarys; | ||||
| @@ -182,7 +185,7 @@ namespace FreeSql.Internal { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		internal string WhereItems<TEntity>(TableInfo table, string aliasAndDot, IEnumerable<TEntity> items) { | ||||
| 		public string WhereItems<TEntity>(TableInfo table, string aliasAndDot, IEnumerable<TEntity> items) { | ||||
| 			if (items == null || items.Any() == false) return null; | ||||
| 			if (table.Primarys.Any() == false) return null; | ||||
| 			var its = items.Where(a => a != null).ToArray(); | ||||
| @@ -231,5 +234,39 @@ namespace FreeSql.Internal { | ||||
| 			} | ||||
| 			return iidx == 1 ? sb.Remove(0, 5).Remove(sb.Length - 1, 1).ToString() : sb.Remove(0, 4).ToString(); | ||||
| 		} | ||||
|  | ||||
| 		public static void PrevReheatConnectionPool(ObjectPool<DbConnection> pool, int minPoolSize) { | ||||
| 			if (minPoolSize <= 0) minPoolSize = Math.Min(5, pool.Policy.PoolSize); | ||||
| 			if (minPoolSize > pool.Policy.PoolSize) minPoolSize = pool.Policy.PoolSize; | ||||
| 			var initTestOk = true; | ||||
| 			var initStartTime = DateTime.Now; | ||||
| 			var initConns = new ConcurrentBag<Object<DbConnection>>(); | ||||
|  | ||||
| 			try { | ||||
| 				var conn = pool.Get(); | ||||
| 				initConns.Add(conn); | ||||
| 				pool.Policy.OnCheckAvailable(conn); | ||||
| 			} catch { | ||||
| 				initTestOk = false; //预热一次失败,后面将不进行 | ||||
| 			} | ||||
| 			for (var a = 1; initTestOk && a < minPoolSize; a += 10) { | ||||
| 				if (initStartTime.Subtract(DateTime.Now).TotalSeconds > 3) break; //预热耗时超过3秒,退出 | ||||
| 				var b = Math.Min(minPoolSize - a, 10); //每10个预热 | ||||
| 				var initTasks = new Task[b]; | ||||
| 				for (var c = 0; c < b; c++) { | ||||
| 					initTasks[c] = Task.Run(() => { | ||||
| 						try { | ||||
| 							var conn = pool.Get(); | ||||
| 							initConns.Add(conn); | ||||
| 							pool.Policy.OnCheckAvailable(conn); | ||||
| 						} catch { | ||||
| 							initTestOk = false;  //有失败,下一组退出预热 | ||||
| 						} | ||||
| 					}); | ||||
| 				} | ||||
| 				Task.WaitAll(initTasks); | ||||
| 			} | ||||
| 			while (initConns.TryTake(out var conn)) pool.Return(conn); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,7 @@ using System.Reflection; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FreeSql.Internal.Model { | ||||
| 	class ReadAnonymousTypeInfo { | ||||
| 	public class ReadAnonymousTypeInfo { | ||||
| 		public PropertyInfo Property { get; set; } | ||||
| 		public string CsName { get; set; } | ||||
| 		public Type CsType { get; set; } | ||||
| @@ -15,5 +15,5 @@ namespace FreeSql.Internal.Model { | ||||
| 		public List<ReadAnonymousTypeInfo> Childs = new List<ReadAnonymousTypeInfo>(); | ||||
| 		public TableInfo Table { get; set; } | ||||
| 	} | ||||
| 	enum ReadAnonymousTypeInfoConsturctorType { Arguments, Properties } | ||||
| 	public enum ReadAnonymousTypeInfoConsturctorType { Arguments, Properties } | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ using System.Collections.Generic; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FreeSql.Internal.Model { | ||||
| 	class SelectColumnInfo { | ||||
| 	public class SelectColumnInfo { | ||||
| 		public ColumnInfo Column { get; set; } | ||||
| 		public SelectTableInfo Table { get; set; } | ||||
| 	} | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| using System.Linq.Expressions; | ||||
|  | ||||
| namespace FreeSql.Internal.Model { | ||||
| 	class SelectTableInfo { | ||||
| 	public class SelectTableInfo { | ||||
| 		public TableInfo Table { get; set; } | ||||
|  | ||||
| 		private string _alias; | ||||
| @@ -18,5 +18,5 @@ namespace FreeSql.Internal.Model { | ||||
| 		public ParameterExpression Parameter { get; set; } | ||||
| 		public SelectTableInfoType Type { get; set; } | ||||
| 	} | ||||
| 	enum SelectTableInfoType { From, LeftJoin, InnerJoin, RightJoin, Parent } | ||||
| 	public enum SelectTableInfoType { From, LeftJoin, InnerJoin, RightJoin, Parent } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| using FreeSql.DataAnnotations; | ||||
| using FreeSql.Internal.Model; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Concurrent; | ||||
| @@ -637,8 +636,9 @@ namespace FreeSql.Internal { | ||||
| 			if (overrieds > 0) { | ||||
| 				cscode.AppendLine("}"); | ||||
| 				Assembly assembly = null; | ||||
| 				if (MethodLazyLoadingComplier.Value == null) throw new Exception("【延时加载】功能需要安装 FreeSql.Extensions.LazyLoading.dll,可前往 nuget 下载"); | ||||
| 				try { | ||||
| 					assembly = Generator.TemplateEngin._compiler.Value.CompileCode(cscode.ToString()); | ||||
| 					assembly = MethodLazyLoadingComplier.Value.Invoke(null, new object[] { cscode.ToString() }) as Assembly; | ||||
| 				} catch (Exception ex) { | ||||
| 					throw new Exception($"【延时加载】{trytbTypeName} 编译错误:{ex.Message}\r\n\r\n{cscode}"); | ||||
| 				} | ||||
| @@ -651,8 +651,12 @@ namespace FreeSql.Internal { | ||||
|  | ||||
| 			return tbc.TryGetValue(entity, out var trytb2) ? trytb2 : trytb; | ||||
| 		} | ||||
| 		static Lazy<MethodInfo> MethodLazyLoadingComplier = new Lazy<MethodInfo>(() => { | ||||
| 			var type = Type.GetType("FreeSql.Extensions.LazyLoading.LazyLoadingComplier,FreeSql.Extensions.LazyLoading"); | ||||
| 			return type.GetMethod("CompileCode"); | ||||
| 		}); | ||||
|  | ||||
| 		internal static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) { | ||||
| 		public 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(); | ||||
| @@ -668,7 +672,7 @@ namespace FreeSql.Internal { | ||||
| 			return ret.ToArray(); | ||||
| 		} | ||||
|  | ||||
| 		internal static Dictionary<Type, bool> dicExecuteArrayRowReadClassOrTuple = new Dictionary<Type, bool> { | ||||
| 		public static Dictionary<Type, bool> dicExecuteArrayRowReadClassOrTuple = new Dictionary<Type, bool> { | ||||
| 			[typeof(bool)] = true, | ||||
| 			[typeof(sbyte)] = true, | ||||
| 			[typeof(short)] = true, | ||||
| @@ -837,12 +841,14 @@ namespace FreeSql.Internal { | ||||
|  | ||||
| 				if (type == typeof(object) && indexes != null) { | ||||
| 					Func<Type, int[], DbDataReader, int, CommonUtils, RowInfo> dynamicFunc = (type2, indexes2, row2, dataindex2, commonUtils2) => { | ||||
| 						dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写 | ||||
| 						var expandodic = (IDictionary<string, object>)expando; | ||||
| 						//dynamic expando = new DynamicDictionary(); //动态类型字段 可读可写 | ||||
| 						var expandodic = new Dictionary<string, object>();// (IDictionary<string, object>)expando; | ||||
| 						var fc = row2.FieldCount; | ||||
| 						for (var a = 0; a < fc; a++) | ||||
| 							//expando[row2.GetName(a)] = row2.GetValue(a); | ||||
| 							expandodic.Add(row2.GetName(a), row2.GetValue(a)); | ||||
| 						return new RowInfo(expando, fc); | ||||
| 						//expando = expandodic; | ||||
| 						return new RowInfo(expandodic, fc); | ||||
| 					}; | ||||
| 					return dynamicFunc;// Expression.Lambda<Func<Type, int[], DbDataReader, int, RowInfo>>(null); | ||||
| 				} | ||||
| @@ -1092,14 +1098,10 @@ namespace FreeSql.Internal { | ||||
| 		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 MethodArrayGetLength = typeof(Array).GetMethod("GetLength", new[] { typeof(int) }); | ||||
| 		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 MethodEnumParse = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) }); | ||||
| 		static MethodInfo MethodConvertChangeType = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) }); | ||||
| 		static MethodInfo MethodTimeSpanFromSeconds = typeof(TimeSpan).GetMethod("FromSeconds"); | ||||
| 		static MethodInfo MethodJTokenParse = typeof(JToken).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 MethodSByteTryParse = typeof(sbyte).GetMethod("TryParse", new[] { typeof(string), typeof(sbyte).MakeByRefType() }); | ||||
| 		static MethodInfo MethodShortTryParse = typeof(short).GetMethod("TryParse", new[] { typeof(string), typeof(short).MakeByRefType() }); | ||||
| 		static MethodInfo MethodIntTryParse = typeof(int).GetMethod("TryParse", new[] { typeof(string), typeof(int).MakeByRefType() }); | ||||
| @@ -1116,6 +1118,8 @@ namespace FreeSql.Internal { | ||||
| 		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 ConcurrentBag<Func<LabelTarget, Expression, string, Expression>> GetDataReaderValueBlockExpressionSwitchTypeFullName = new ConcurrentBag<Func<LabelTarget, Expression, string, Expression>>(); | ||||
| 		public static Expression GetDataReaderValueBlockExpression(Type type, Expression value) { | ||||
| 			var returnTarget = Expression.Label(typeof(object)); | ||||
| 			var valueExp = Expression.Variable(typeof(object), "locvalue"); | ||||
| @@ -1177,16 +1181,6 @@ namespace FreeSql.Internal { | ||||
| 							   } | ||||
| 						   ); | ||||
| 						break; | ||||
| 					case "MygisPoint": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisPoint))); | ||||
| 					case "MygisLineString": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisLineString))); | ||||
| 					case "MygisPolygon": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisPolygon))); | ||||
| 					case "MygisMultiPoint": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiPoint))); | ||||
| 					case "MygisMultiLineString": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiLineString))); | ||||
| 					case "MygisMultiPolygon": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiPolygon))); | ||||
| 					case "Newtonsoft.Json.Linq.JToken": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJTokenParse, Expression.Convert(valueExp, typeof(string))), typeof(JToken))); | ||||
| 					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 "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": | ||||
| 						ParameterExpression tryparseVarTsExp, valueStrExp; | ||||
| @@ -1373,6 +1367,12 @@ namespace FreeSql.Internal { | ||||
| 							typeof(object)) | ||||
| 						); | ||||
| 						break; | ||||
| 					default: | ||||
| 						foreach (var switchFunc in GetDataReaderValueBlockExpressionSwitchTypeFullName) { | ||||
| 							var switchFuncRet = switchFunc(returnTarget, valueExp, type.FullName); | ||||
| 							if (switchFuncRet != null) return switchFuncRet; | ||||
| 						} | ||||
| 						break; | ||||
| 				} | ||||
| 				Expression switchExp = null; | ||||
| 				if (tryparseExp != null) | ||||
| @@ -1437,45 +1437,7 @@ namespace FreeSql.Internal { | ||||
| 			}); | ||||
| 			return func(value); | ||||
| 		} | ||||
| 		internal static object GetDataReaderValue22(Type type, object value) { | ||||
| 			if (value == null || value == DBNull.Value) return Activator.CreateInstance(type); | ||||
| 			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(GetDataReaderValue22(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) { | ||||
| 		public static string GetCsName(string name) { | ||||
| 			name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_"); | ||||
| 			return char.IsLetter(name, 0) ? name : string.Concat("_", name); | ||||
| 		} | ||||
|   | ||||
| @@ -20,7 +20,7 @@ namespace FreeSql.MySql.Curd { | ||||
| 		public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(5000, 3000); | ||||
| 
 | ||||
| 
 | ||||
| 		internal override long RawExecuteIdentity() { | ||||
| 		protected override long RawExecuteIdentity() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 
 | ||||
| @@ -41,7 +41,7 @@ namespace FreeSql.MySql.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal override Task<long> RawExecuteIdentityAsync() { | ||||
| 		async protected override Task<long> RawExecuteIdentityAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 
 | ||||
| @@ -62,7 +62,7 @@ namespace FreeSql.MySql.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		internal override List<T1> RawExecuteInserted() { | ||||
| 		protected override List<T1> RawExecuteInserted() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -92,7 +92,7 @@ namespace FreeSql.MySql.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal override Task<List<T1>> RawExecuteInsertedAsync() { | ||||
| 		async protected override Task<List<T1>> RawExecuteInsertedAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -21,7 +21,7 @@ namespace FreeSql.MySql.Curd { | ||||
| 		public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(500, 3000); | ||||
| 
 | ||||
| 
 | ||||
| 		internal override List<T1> RawExecuteUpdated() { | ||||
| 		protected override List<T1> RawExecuteUpdated() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -53,7 +53,7 @@ namespace FreeSql.MySql.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal override Task<List<T1>> RawExecuteUpdatedAsync() { | ||||
| 		async protected override Task<List<T1>> RawExecuteUpdatedAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -0,0 +1,28 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<Version>0.6.1</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 MySql 5.6</Description> | ||||
| 		<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl> | ||||
| 		<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl> | ||||
| 		<RepositoryType>git</RepositoryType> | ||||
| 		<PackageLicenseExpression>MIT</PackageLicenseExpression> | ||||
| 		<PackageTags>FreeSql;ORM</PackageTags> | ||||
| 		<PackageId>$(AssemblyName)</PackageId> | ||||
| 		<Title>$(AssemblyName)</Title> | ||||
| 		<IsPackable>true</IsPackable> | ||||
| 		<GenerateAssemblyInfo>true</GenerateAssemblyInfo> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="MySql.Data" Version="8.0.15" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\..\FreeSql\FreeSql.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| </Project> | ||||
| @@ -1,5 +1,4 @@ | ||||
| using FreeSql.Internal; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using MySql.Data.MySqlClient; | ||||
| using SafeObjectPool; | ||||
| using System; | ||||
| @@ -11,8 +10,8 @@ using System.Threading; | ||||
| namespace FreeSql.MySql { | ||||
| 	class MySqlAdo : FreeSql.Internal.CommonProvider.AdoProvider { | ||||
| 
 | ||||
| 		public MySqlAdo() : base(null, null, DataType.MySql) { } | ||||
| 		public MySqlAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.MySql) { | ||||
| 		public MySqlAdo() : base(DataType.MySql) { } | ||||
| 		public MySqlAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.MySql) { | ||||
| 			base._util = util; | ||||
| 			if (!string.IsNullOrEmpty(masterConnectionString)) | ||||
| 				MasterPool = new MySqlConnectionPool("主库", masterConnectionString, null, null); | ||||
| @@ -77,7 +77,7 @@ namespace FreeSql.MySql { | ||||
| 					_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase); | ||||
| 				} | ||||
| 
 | ||||
| 				FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize); | ||||
| 				FreeSql.Internal.CommonUtils.PrevReheatConnectionPool(_pool, minPoolSize); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| @@ -12,7 +12,7 @@ namespace FreeSql.MySql { | ||||
| 
 | ||||
| 		public MySqlExpression(CommonUtils common) : base(common) { } | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			switch (exp.NodeType) { | ||||
| 				case ExpressionType.Convert: | ||||
| @@ -132,7 +132,7 @@ namespace FreeSql.MySql { | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Empty": return "''"; | ||||
| @@ -145,7 +145,7 @@ namespace FreeSql.MySql { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Now": return "now()"; | ||||
| @@ -173,7 +173,7 @@ namespace FreeSql.MySql { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Zero": return "0"; | ||||
| @@ -199,7 +199,7 @@ namespace FreeSql.MySql { | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -272,7 +272,7 @@ namespace FreeSql.MySql { | ||||
| 			} | ||||
| 			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			switch (exp.Method.Name) { | ||||
| 				case "Abs": return $"abs({getExp(exp.Arguments[0])})"; | ||||
| @@ -298,7 +298,7 @@ namespace FreeSql.MySql { | ||||
| 			} | ||||
| 			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -341,7 +341,7 @@ namespace FreeSql.MySql { | ||||
| 			} | ||||
| 			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -371,7 +371,7 @@ namespace FreeSql.MySql { | ||||
| 			} | ||||
| 			throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -1,16 +1,14 @@ | ||||
| using FreeSql.Internal; | ||||
| using FreeSql.Internal.CommonProvider; | ||||
| using FreeSql.MySql.Curd; | ||||
| using Microsoft.Extensions.Caching.Distributed; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Data.Common; | ||||
| using System.Linq.Expressions; | ||||
| 
 | ||||
| namespace FreeSql.MySql { | ||||
| 
 | ||||
| 	class MySqlProvider<TMark> : IFreeSql<TMark> { | ||||
| 	public class MySqlProvider<TMark> : IFreeSql<TMark> { | ||||
| 
 | ||||
| 		static MySqlProvider() { | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisPoint)] = true; | ||||
| @@ -19,6 +17,19 @@ namespace FreeSql.MySql { | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisMultiPoint)] = true; | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisMultiLineString)] = true; | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisMultiPolygon)] = true; | ||||
| 
 | ||||
| 			var MethodMygisGeometryParse = typeof(MygisGeometry).GetMethod("Parse", new[] { typeof(string) }); | ||||
| 			Utils.GetDataReaderValueBlockExpressionSwitchTypeFullName.Add((LabelTarget returnTarget, Expression valueExp, string typeFullName) => { | ||||
| 				switch (typeFullName) { | ||||
| 					case "MygisPoint": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisPoint))); | ||||
| 					case "MygisLineString": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisLineString))); | ||||
| 					case "MygisPolygon": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisPolygon))); | ||||
| 					case "MygisMultiPoint": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiPoint))); | ||||
| 					case "MygisMultiLineString": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiLineString))); | ||||
| 					case "MygisMultiPolygon": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiPolygon))); | ||||
| 				} | ||||
| 				return null; | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		public ISelect<T1> Select<T1>() where T1 : class => new MySqlSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null); | ||||
| @@ -34,17 +45,13 @@ namespace FreeSql.MySql { | ||||
| 
 | ||||
| 		public IAdo Ado { get; } | ||||
| 		public IAop Aop { get; } | ||||
| 		public ICache Cache { get; } | ||||
| 		public ICodeFirst CodeFirst { get; } | ||||
| 		public IDbFirst DbFirst { get; } | ||||
| 		public MySqlProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) { | ||||
| 			if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.MySql"); | ||||
| 
 | ||||
| 		public MySqlProvider(string masterConnectionString, string[] slaveConnectionString) { | ||||
| 			this.InternalCommonUtils = new MySqlUtils(this); | ||||
| 			this.InternalCommonExpression = new MySqlExpression(this.InternalCommonUtils); | ||||
| 
 | ||||
| 			this.Cache = new CacheProvider(cache, log); | ||||
| 			this.Ado = new MySqlAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString); | ||||
| 			this.Ado = new MySqlAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); | ||||
| 			this.Aop = new AopProvider(); | ||||
| 
 | ||||
| 			this.DbFirst = new MySqlDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); | ||||
| @@ -65,7 +72,6 @@ namespace FreeSql.MySql { | ||||
| 		public void Dispose() { | ||||
| 			if (_isdisposed) return; | ||||
| 			(this.Ado as AdoProvider).Dispose(); | ||||
| 			(this.Cache as CacheProvider)?.Dispose(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -5,6 +5,8 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Data.Common; | ||||
| using System.Linq; | ||||
| using System.Linq.Expressions; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| 
 | ||||
| namespace FreeSql.MySql { | ||||
| @@ -13,7 +15,7 @@ namespace FreeSql.MySql { | ||||
| 		public MySqlUtils(IFreeSql orm) : base(orm) { | ||||
| 		} | ||||
| 
 | ||||
| 		internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) { | ||||
| 		public override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) { | ||||
| 			if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; | ||||
| 			var ret = new MySqlParameter { ParameterName = QuoteParamterName(parameterName), Value = value }; | ||||
| 			var tp = _orm.CodeFirst.GetDbInfo(type)?.type; | ||||
| @@ -28,7 +30,7 @@ namespace FreeSql.MySql { | ||||
| 			return ret; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) => | ||||
| 		public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => | ||||
| 			Utils.GetDbParamtersByObject<MySqlParameter>(sql, obj, "?", (name, type, value) => { | ||||
| 				var ret = new MySqlParameter { ParameterName = $"?{name}", Value = value }; | ||||
| 				var tp = _orm.CodeFirst.GetDbInfo(type)?.type; | ||||
| @@ -42,24 +44,24 @@ namespace FreeSql.MySql { | ||||
| 				return ret; | ||||
| 			}); | ||||
| 
 | ||||
| 		internal override string FormatSql(string sql, params object[] args) => sql?.FormatMySql(args); | ||||
| 		internal override string QuoteSqlName(string name) { | ||||
| 		public override string FormatSql(string sql, params object[] args) => sql?.FormatMySql(args); | ||||
| 		public override string QuoteSqlName(string name) { | ||||
| 			var nametrim = name.Trim(); | ||||
| 			if (nametrim.StartsWith("(") && nametrim.EndsWith(")")) | ||||
| 				return nametrim; //原生SQL | ||||
| 			return $"`{nametrim.Trim('`').Replace(".", "`.`")}`"; | ||||
| 		} | ||||
| 		internal override string TrimQuoteSqlName(string name) { | ||||
| 		public 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 IsNull(string sql, object value) => $"ifnull({sql}, {value})"; | ||||
| 		internal override string StringConcat(string[] objs, Type[] types) => $"concat({string.Join(", ", objs)})"; | ||||
| 		internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}"; | ||||
| 		internal override string QuoteWriteParamter(Type type, string paramterName) { | ||||
| 		public override string QuoteParamterName(string name) => $"?{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; | ||||
| 		public override string IsNull(string sql, object value) => $"ifnull({sql}, {value})"; | ||||
| 		public override string StringConcat(string[] objs, Type[] types) => $"concat({string.Join(", ", objs)})"; | ||||
| 		public override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}"; | ||||
| 		public override string QuoteWriteParamter(Type type, string paramterName) { | ||||
| 			switch (type.FullName) { | ||||
| 				case "MygisPoint": | ||||
| 				case "MygisLineString":  | ||||
| @@ -71,7 +73,7 @@ namespace FreeSql.MySql { | ||||
| 			return paramterName; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string QuoteReadColumn(Type type, string columnName) { | ||||
| 		public override string QuoteReadColumn(Type type, string columnName) { | ||||
| 			switch (type.FullName) { | ||||
| 				case "MygisPoint": | ||||
| 				case "MygisLineString": | ||||
| @@ -83,7 +85,7 @@ namespace FreeSql.MySql { | ||||
| 			return columnName; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) { | ||||
| 		public override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) { | ||||
| 			if (value == null) return "NULL"; | ||||
| 			if (type == typeof(byte[])) { | ||||
| 				var bytes = value as byte[]; | ||||
| @@ -80,7 +80,7 @@ namespace FreeSql.Oracle.Curd { | ||||
| 		} | ||||
| 
 | ||||
| 		ColumnInfo _identCol; | ||||
| 		internal override long RawExecuteIdentity() { | ||||
| 		protected override long RawExecuteIdentity() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 
 | ||||
| @@ -123,7 +123,7 @@ namespace FreeSql.Oracle.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal override Task<long> RawExecuteIdentityAsync() { | ||||
| 		async protected override Task<long> RawExecuteIdentityAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 
 | ||||
| @@ -167,14 +167,14 @@ namespace FreeSql.Oracle.Curd { | ||||
| 			return ret; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override List<T1> RawExecuteInserted() { | ||||
| 		protected override List<T1> RawExecuteInserted() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| 			this.RawExecuteAffrows(); | ||||
| 			return _source; | ||||
| 		} | ||||
| 		async internal override Task<List<T1>> RawExecuteInsertedAsync() { | ||||
| 		async protected override Task<List<T1>> RawExecuteInsertedAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -21,10 +21,10 @@ namespace FreeSql.Oracle.Curd { | ||||
| 		public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(200, 999); | ||||
| 
 | ||||
| 
 | ||||
| 		internal override List<T1> RawExecuteUpdated() { | ||||
| 		protected override List<T1> RawExecuteUpdated() { | ||||
| 			throw new NotImplementedException(); | ||||
| 		} | ||||
| 		internal override Task<List<T1>> RawExecuteUpdatedAsync() { | ||||
| 		protected override Task<List<T1>> RawExecuteUpdatedAsync() { | ||||
| 			throw new NotImplementedException(); | ||||
| 		} | ||||
| 
 | ||||
| @@ -0,0 +1,29 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<Version>0.6.1</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 Oracle 11</Description> | ||||
| 		<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl> | ||||
| 		<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl> | ||||
| 		<RepositoryType>git</RepositoryType> | ||||
| 		<PackageLicenseExpression>MIT</PackageLicenseExpression> | ||||
| 		<PackageTags>FreeSql;ORM</PackageTags> | ||||
| 		<PackageId>$(AssemblyName)</PackageId> | ||||
| 		<Title>$(AssemblyName)</Title> | ||||
| 		<IsPackable>true</IsPackable> | ||||
| 		<GenerateAssemblyInfo>true</GenerateAssemblyInfo> | ||||
| 	</PropertyGroup> | ||||
| 	 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.18.5" /> | ||||
| 	</ItemGroup> | ||||
| 	 | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\..\FreeSql\FreeSql.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 	 | ||||
| </Project> | ||||
| 	 | ||||
| @@ -1,5 +1,4 @@ | ||||
| using FreeSql.Internal; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Oracle.ManagedDataAccess.Client; | ||||
| using SafeObjectPool; | ||||
| using System; | ||||
| @@ -10,8 +9,8 @@ using System.Threading; | ||||
| 
 | ||||
| namespace FreeSql.Oracle { | ||||
| 	class OracleAdo : FreeSql.Internal.CommonProvider.AdoProvider { | ||||
| 		public OracleAdo() : base(null, null, DataType.Oracle) { } | ||||
| 		public OracleAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.Oracle) { | ||||
| 		public OracleAdo() : base(DataType.Oracle) { } | ||||
| 		public OracleAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.Oracle) { | ||||
| 			base._util = util; | ||||
| 			if (!string.IsNullOrEmpty(masterConnectionString)) | ||||
| 				MasterPool = new OracleConnectionPool("主库", masterConnectionString, null, null); | ||||
| @@ -91,7 +91,7 @@ namespace FreeSql.Oracle { | ||||
| 					_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase); | ||||
| 				} | ||||
| 
 | ||||
| 				FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize); | ||||
| 				FreeSql.Internal.CommonUtils.PrevReheatConnectionPool(_pool, minPoolSize); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| @@ -12,7 +12,7 @@ namespace FreeSql.Oracle { | ||||
| 
 | ||||
| 		public OracleExpression(CommonUtils common) : base(common) { } | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			switch (exp.NodeType) { | ||||
| 				case ExpressionType.Convert: | ||||
| @@ -132,7 +132,7 @@ namespace FreeSql.Oracle { | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Empty": return "''"; | ||||
| @@ -145,7 +145,7 @@ namespace FreeSql.Oracle { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Now": return "systimestamp"; | ||||
| @@ -173,7 +173,7 @@ namespace FreeSql.Oracle { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Zero": return "numtodsinterval(0,'second')"; | ||||
| @@ -199,7 +199,7 @@ namespace FreeSql.Oracle { | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -272,7 +272,7 @@ namespace FreeSql.Oracle { | ||||
| 			} | ||||
| 			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			switch (exp.Method.Name) { | ||||
| 				case "Abs": return $"abs({getExp(exp.Arguments[0])})"; | ||||
| @@ -299,7 +299,7 @@ namespace FreeSql.Oracle { | ||||
| 			} | ||||
| 			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -342,7 +342,7 @@ namespace FreeSql.Oracle { | ||||
| 			} | ||||
| 			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -372,7 +372,7 @@ namespace FreeSql.Oracle { | ||||
| 			} | ||||
| 			throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -1,16 +1,13 @@ | ||||
| using FreeSql.Internal; | ||||
| using FreeSql.Internal.CommonProvider; | ||||
| using FreeSql.Oracle.Curd; | ||||
| using Microsoft.Extensions.Caching.Distributed; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Data.Common; | ||||
| 
 | ||||
| namespace FreeSql.Oracle { | ||||
| 
 | ||||
| 	class OracleProvider<TMark> : IFreeSql<TMark> { | ||||
| 	public class OracleProvider<TMark> : IFreeSql<TMark> { | ||||
| 
 | ||||
| 		public ISelect<T1> Select<T1>() where T1 : class => new OracleSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null); | ||||
| 		public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new OracleSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere); | ||||
| @@ -25,17 +22,13 @@ namespace FreeSql.Oracle { | ||||
| 
 | ||||
| 		public IAdo Ado { get; } | ||||
| 		public IAop Aop { get; } | ||||
| 		public ICache Cache { get; } | ||||
| 		public ICodeFirst CodeFirst { get; } | ||||
| 		public IDbFirst DbFirst { get; } | ||||
| 		public OracleProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) { | ||||
| 			if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.Oracle"); | ||||
| 
 | ||||
| 		public OracleProvider(string masterConnectionString, string[] slaveConnectionString) { | ||||
| 			this.InternalCommonUtils = new OracleUtils(this); | ||||
| 			this.InternalCommonExpression = new OracleExpression(this.InternalCommonUtils); | ||||
| 
 | ||||
| 			this.Cache = new CacheProvider(cache, log); | ||||
| 			this.Ado = new OracleAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString); | ||||
| 			this.Ado = new OracleAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); | ||||
| 			this.Aop = new AopProvider(); | ||||
| 
 | ||||
| 			this.DbFirst = new OracleDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); | ||||
| @@ -56,7 +49,6 @@ namespace FreeSql.Oracle { | ||||
| 		public void Dispose() { | ||||
| 			if (_isdisposed) return; | ||||
| 			(this.Ado as AdoProvider).Dispose(); | ||||
| 			(this.Cache as CacheProvider)?.Dispose(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -4,6 +4,7 @@ using Oracle.ManagedDataAccess.Client; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Data.Common; | ||||
| using System.Linq.Expressions; | ||||
| using System.Text; | ||||
| 
 | ||||
| namespace FreeSql.Oracle { | ||||
| @@ -12,7 +13,7 @@ namespace FreeSql.Oracle { | ||||
| 		public OracleUtils(IFreeSql orm) : base(orm) { | ||||
| 		} | ||||
| 
 | ||||
| 		internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) { | ||||
| 		public override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) { | ||||
| 			if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; | ||||
| 			var dbtype = (OracleDbType)_orm.CodeFirst.GetDbInfo(type)?.type; | ||||
| 			if (dbtype == OracleDbType.Boolean) { | ||||
| @@ -25,7 +26,7 @@ namespace FreeSql.Oracle { | ||||
| 			return ret; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) => | ||||
| 		public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => | ||||
| 			Utils.GetDbParamtersByObject<OracleParameter>(sql, obj, ":", (name, type, value) => { | ||||
| 				var dbtype = (OracleDbType)_orm.CodeFirst.GetDbInfo(type)?.type; | ||||
| 				if (dbtype == OracleDbType.Boolean) { | ||||
| @@ -37,28 +38,28 @@ namespace FreeSql.Oracle { | ||||
| 				return ret; | ||||
| 			}); | ||||
| 
 | ||||
| 		internal override string FormatSql(string sql, params object[] args) => sql?.FormatOracleSQL(args); | ||||
| 		internal override string QuoteSqlName(string name) { | ||||
| 		public override string FormatSql(string sql, params object[] args) => sql?.FormatOracleSQL(args); | ||||
| 		public override string QuoteSqlName(string name) { | ||||
| 			var nametrim = name.Trim(); | ||||
| 			if (nametrim.StartsWith("(") && nametrim.EndsWith(")")) | ||||
| 				return nametrim; //原生SQL | ||||
| 			return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\""; | ||||
| 		} | ||||
| 		internal override string TrimQuoteSqlName(string name) { | ||||
| 		public 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 IsNull(string sql, object value) => $"nvl({sql}, {value})"; | ||||
| 		internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}"; | ||||
| 		internal override string Mod(string left, string right, Type leftType, Type rightType) => $"mod({left}, {right})"; | ||||
| 		public override string QuoteParamterName(string name) => $":{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; | ||||
| 		public override string IsNull(string sql, object value) => $"nvl({sql}, {value})"; | ||||
| 		public override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}"; | ||||
| 		public override string Mod(string left, string right, Type leftType, Type rightType) => $"mod({left}, {right})"; | ||||
| 
 | ||||
| 		internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName; | ||||
| 		internal override string QuoteReadColumn(Type type, string columnName) => columnName; | ||||
| 		public override string QuoteWriteParamter(Type type, string paramterName) => paramterName; | ||||
| 		public override string QuoteReadColumn(Type type, string columnName) => columnName; | ||||
| 
 | ||||
| 		internal override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) { | ||||
| 		public override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) { | ||||
| 			if (value == null) return "NULL"; | ||||
| 			if (type == typeof(byte[])) { | ||||
| 				var bytes = value as byte[]; | ||||
| @@ -21,7 +21,7 @@ namespace FreeSql.PostgreSQL.Curd { | ||||
| 		public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(5000, 3000); | ||||
| 
 | ||||
| 
 | ||||
| 		internal override long RawExecuteIdentity() { | ||||
| 		protected override long RawExecuteIdentity() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 
 | ||||
| @@ -60,7 +60,7 @@ namespace FreeSql.PostgreSQL.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal override Task<long> RawExecuteIdentityAsync() { | ||||
| 		async protected override Task<long> RawExecuteIdentityAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return 0; | ||||
| 
 | ||||
| @@ -100,7 +100,7 @@ namespace FreeSql.PostgreSQL.Curd { | ||||
| 			return ret; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override List<T1> RawExecuteInserted() { | ||||
| 		protected override List<T1> RawExecuteInserted() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -130,7 +130,7 @@ namespace FreeSql.PostgreSQL.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal override Task<List<T1>> RawExecuteInsertedAsync() { | ||||
| 		async protected override Task<List<T1>> RawExecuteInsertedAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -21,7 +21,7 @@ namespace FreeSql.PostgreSQL.Curd { | ||||
| 		public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(500, 3000); | ||||
| 
 | ||||
| 
 | ||||
| 		internal override List<T1> RawExecuteUpdated() { | ||||
| 		protected override List<T1> RawExecuteUpdated() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -53,7 +53,7 @@ namespace FreeSql.PostgreSQL.Curd { | ||||
| 			this.ClearData(); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		async internal override Task<List<T1>> RawExecuteUpdatedAsync() { | ||||
| 		async protected override Task<List<T1>> RawExecuteUpdatedAsync() { | ||||
| 			var sql = this.ToSql(); | ||||
| 			if (string.IsNullOrEmpty(sql)) return new List<T1>(); | ||||
| 
 | ||||
| @@ -0,0 +1,29 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<Version>0.6.1</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 PostgreSQL 9.5</Description> | ||||
| 		<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl> | ||||
| 		<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl> | ||||
| 		<RepositoryType>git</RepositoryType> | ||||
| 		<PackageLicenseExpression>MIT</PackageLicenseExpression> | ||||
| 		<PackageTags>FreeSql;ORM</PackageTags> | ||||
| 		<PackageId>$(AssemblyName)</PackageId> | ||||
| 		<Title>$(AssemblyName)</Title> | ||||
| 		<IsPackable>true</IsPackable> | ||||
| 		<GenerateAssemblyInfo>true</GenerateAssemblyInfo> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Newtonsoft.Json" Version="12.0.1" /> | ||||
| 		<PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.5" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\..\FreeSql\FreeSql.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| </Project> | ||||
| @@ -1,5 +1,4 @@ | ||||
| using FreeSql.Internal; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using Npgsql; | ||||
| using SafeObjectPool; | ||||
| @@ -12,8 +11,8 @@ using System.Threading; | ||||
| 
 | ||||
| namespace FreeSql.PostgreSQL { | ||||
| 	class PostgreSQLAdo : FreeSql.Internal.CommonProvider.AdoProvider { | ||||
| 		public PostgreSQLAdo() : base(null, null, DataType.PostgreSQL) { } | ||||
| 		public PostgreSQLAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.PostgreSQL) { | ||||
| 		public PostgreSQLAdo() : base(DataType.PostgreSQL) { } | ||||
| 		public PostgreSQLAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings) : base(DataType.PostgreSQL) { | ||||
| 			base._util = util; | ||||
| 			if (!string.IsNullOrEmpty(masterConnectionString)) | ||||
| 				MasterPool = new PostgreSQLConnectionPool("主库", masterConnectionString, null, null); | ||||
| @@ -86,7 +86,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 					_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase); | ||||
| 				} | ||||
| 
 | ||||
| 				FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize); | ||||
| 				FreeSql.Internal.CommonUtils.PrevReheatConnectionPool(_pool, minPoolSize); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| @@ -13,7 +13,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 
 | ||||
| 		public PostgreSQLExpression(CommonUtils common) : base(common) { } | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			switch (exp.NodeType) { | ||||
| 				case ExpressionType.Convert: | ||||
| @@ -230,7 +230,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Empty": return "''"; | ||||
| @@ -243,7 +243,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Now": return "current_timestamp"; | ||||
| @@ -271,7 +271,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) { | ||||
| 			if (exp.Expression == null) { | ||||
| 				switch (exp.Member.Name) { | ||||
| 					case "Zero": return "0"; | ||||
| @@ -297,7 +297,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			return null; | ||||
| 		} | ||||
| 
 | ||||
| 		internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -372,7 +372,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			} | ||||
| 			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			switch (exp.Method.Name) { | ||||
| 				case "Abs": return $"abs({getExp(exp.Arguments[0])})"; | ||||
| @@ -398,7 +398,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			} | ||||
| 			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -441,7 +441,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			} | ||||
| 			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -471,7 +471,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 			} | ||||
| 			throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析"); | ||||
| 		} | ||||
| 		internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 		public override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) { | ||||
| 			Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); | ||||
| 			if (exp.Object == null) { | ||||
| 				switch (exp.Method.Name) { | ||||
| @@ -1,9 +1,6 @@ | ||||
| using FreeSql.Internal; | ||||
| using FreeSql.Internal.CommonProvider; | ||||
| using FreeSql.PostgreSQL.Curd; | ||||
| using Microsoft.Extensions.Caching.Distributed; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using Npgsql.LegacyPostgis; | ||||
| using NpgsqlTypes; | ||||
| @@ -11,12 +8,13 @@ using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Data.Common; | ||||
| using System.Linq.Expressions; | ||||
| using System.Net; | ||||
| using System.Net.NetworkInformation; | ||||
| 
 | ||||
| namespace FreeSql.PostgreSQL { | ||||
| 
 | ||||
| 	class PostgreSQLProvider<TMark> : IFreeSql<TMark> { | ||||
| 	public class PostgreSQLProvider<TMark> : IFreeSql<TMark> { | ||||
| 
 | ||||
| 		static PostgreSQLProvider() { | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BitArray)] = true; | ||||
| @@ -46,6 +44,19 @@ namespace FreeSql.PostgreSQL { | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JToken)] = true; | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JObject)] = true; | ||||
| 			Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JArray)] = true; | ||||
| 
 | ||||
| 			var MethodJTokenParse = typeof(JToken).GetMethod("Parse", new[] { typeof(string) }); | ||||
| 			var MethodJObjectParse = typeof(JObject).GetMethod("Parse", new[] { typeof(string) }); | ||||
| 			var MethodJArrayParse = typeof(JArray).GetMethod("Parse", new[] { typeof(string) }); | ||||
| 			Utils.GetDataReaderValueBlockExpressionSwitchTypeFullName.Add((LabelTarget returnTarget, Expression valueExp, string typeFullName) => { | ||||
| 				switch (typeFullName) { | ||||
| 					case "Newtonsoft.Json.Linq.JToken": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJTokenParse, Expression.Convert(valueExp, typeof(string))), typeof(JToken))); | ||||
| 					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 "Npgsql.LegacyPostgis.PostgisGeometry": return Expression.Return(returnTarget, valueExp); | ||||
| 				} | ||||
| 				return null; | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		public ISelect<T1> Select<T1>() where T1 : class => new PostgreSQLSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null); | ||||
| @@ -61,17 +72,13 @@ namespace FreeSql.PostgreSQL { | ||||
| 
 | ||||
| 		public IAdo Ado { get; } | ||||
| 		public IAop Aop { get; } | ||||
| 		public ICache Cache { get; } | ||||
| 		public ICodeFirst CodeFirst { get; } | ||||
| 		public IDbFirst DbFirst { get; } | ||||
| 		public PostgreSQLProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) { | ||||
| 			if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.PostgreSQL"); | ||||
| 
 | ||||
| 		public PostgreSQLProvider(string masterConnectionString, string[] slaveConnectionString) { | ||||
| 			this.InternalCommonUtils = new PostgreSQLUtils(this); | ||||
| 			this.InternalCommonExpression = new PostgreSQLExpression(this.InternalCommonUtils); | ||||
| 
 | ||||
| 			this.Cache = new CacheProvider(cache, log); | ||||
| 			this.Ado = new PostgreSQLAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString); | ||||
| 			this.Ado = new PostgreSQLAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString); | ||||
| 			this.Aop = new AopProvider(); | ||||
| 
 | ||||
| 			this.DbFirst = new PostgreSQLDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); | ||||
| @@ -92,7 +99,6 @@ namespace FreeSql.PostgreSQL { | ||||
| 		public void Dispose() { | ||||
| 			if (_isdisposed) return; | ||||
| 			(this.Ado as AdoProvider).Dispose(); | ||||
| 			(this.Cache as CacheProvider)?.Dispose(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 28810
					28810