mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-10-31 15:55:27 +08:00 
			
		
		
		
	- 增加 NavigateAttribute 配置导航关系;
- 修复 LinqToSql 方法,开启自动迁移时,迁移了无关类的 bug; - 修复 Oracle DbFirst date(7) 类型未处理的 bug;#57 - 修复 AsSelect().Any() 未给其他条件时,产生 null bug; - 增加 FreeSql.Extensions.LazyLoading 对 .net 4.5 的支持; - 优化 MySql CodeFirst 增加 DateTime 迁移后,默认值为 0000-00-00 导致读取失败的 bug; - 优化 LazyLoading 友好错误提示;
This commit is contained in:
		| @@ -1,8 +1,8 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<TargetFrameworks>netstandard2.0;net45</TargetFrameworks> | ||||
| 		<Version>0.6.4</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 扩展包,可实现【延时加载】属性.</Description> | ||||
| @@ -17,9 +17,13 @@ | ||||
| 		<GenerateAssemblyInfo>true</GenerateAssemblyInfo> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> | ||||
| 		<PackageReference Include="CS-Script.Core" Version="1.1.1" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> | ||||
| 		<DefineConstants>ns20;netstandard20</DefineConstants> | ||||
| 	</PropertyGroup> | ||||
| 	 | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\..\FreeSql\FreeSql.csproj" /> | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| using System; | ||||
| using Microsoft.CSharp; | ||||
| using System; | ||||
| using System.CodeDom.Compiler; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| @@ -7,6 +9,7 @@ namespace FreeSql.Extensions.LazyLoading { | ||||
|  | ||||
| 	public class LazyLoadingComplier { | ||||
|  | ||||
| #if ns20 | ||||
| 		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(); | ||||
| @@ -26,5 +29,28 @@ namespace FreeSql.Extensions.LazyLoading { | ||||
| 		public static Assembly CompileCode(string cscode) { | ||||
| 			return _compiler.Value.CompileCode(cscode); | ||||
| 		} | ||||
| #else | ||||
|  | ||||
|  | ||||
| 		public static Assembly CompileCode(string cscode) { | ||||
|  | ||||
| 			using (var compiler = CodeDomProvider.CreateProvider("cs")) { | ||||
|  | ||||
| 				var objCompilerParameters = new CompilerParameters(); | ||||
| 				objCompilerParameters.ReferencedAssemblies.Add("System.dll"); | ||||
| 				objCompilerParameters.ReferencedAssemblies.Add("FreeSql.dll"); | ||||
| 				objCompilerParameters.GenerateExecutable = false; | ||||
| 				objCompilerParameters.GenerateInMemory = true; | ||||
|  | ||||
| 				CompilerResults cr = compiler.CompileAssemblyFromSource(objCompilerParameters, cscode); | ||||
|  | ||||
| 				if (cr.Errors.Count > 0) | ||||
| 					throw new Exception(cr.Errors[0].ErrorText); | ||||
|  | ||||
| 				return cr.CompiledAssembly; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| #endif | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,6 @@ | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="FreeSql.DbContext" Version="0.6.1" /> | ||||
| 		<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,6 +14,7 @@ | ||||
| 	</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" /> | ||||
|   | ||||
| @@ -210,10 +210,72 @@ namespace FreeSql.Tests { | ||||
| 			[Column(Name = "release_time")] | ||||
| 			public int ReleaseTime { get; set; } | ||||
|  | ||||
| 			public DateTime testaddtime { get; set; } | ||||
| 			public DateTime? testaddtime2 { get; set; } | ||||
| 		} | ||||
|  | ||||
| 		public class NewsArticleDto : NewsArticle { | ||||
|  | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		public class TaskBuildInfo { | ||||
| 			[FreeSql.DataAnnotations.Column(IsPrimary = true)] | ||||
| 			public Guid Id { get; set; } | ||||
| 			public Guid TbId { get; set; } | ||||
| 			public Guid DataBaseConfigId { get; set; } | ||||
| 			public string Name { get; set; } | ||||
| 			public int Level { get; set; } | ||||
|  | ||||
| 			[Column(IsIgnore = true)] | ||||
| 			public virtual TaskBuild TaskBuild { get; set; } | ||||
| 		} | ||||
| 		public class Templates { | ||||
| 			[Column(IsPrimary = true)] | ||||
| 			public Guid Id { get; set; } | ||||
| 			public string Title { get; set; } | ||||
| 			public DateTime AddTime { get; set; } = DateTime.Now; | ||||
| 			public DateTime EditTime { get; set; } | ||||
| 			[Column(DbType = "text")] | ||||
| 			public string Code { get; set; } | ||||
| 		} | ||||
| 		public class TaskBuild { | ||||
|  | ||||
| 			[FreeSql.DataAnnotations.Column(IsPrimary = true)] | ||||
| 			public Guid Id { get; set; } | ||||
| 			public string TaskName { get; set; } | ||||
| 			public Guid TemplatesId { get; set; } | ||||
| 			public string GeneratePath { get; set; } | ||||
| 			public string FileName { get; set; } | ||||
| 			public string NamespaceName { get; set; } | ||||
| 			public bool OptionsEntity01 { get; set; } = false; | ||||
| 			public bool OptionsEntity02 { get; set; } = false; | ||||
| 			public bool OptionsEntity03 { get; set; } = false; | ||||
| 			public bool OptionsEntity04 { get; set; } = false; | ||||
|  | ||||
| 			[Navigate("TbId")] | ||||
| 			public virtual ICollection<TaskBuildInfo> Builds { get; set; } | ||||
| 			public Templates Templates { get; set; } | ||||
| 		} | ||||
|  | ||||
| 		[Fact] | ||||
| 		public void Test1() { | ||||
| 			g.sqlite.SetDbContextOptions(opt => opt.EnableAddOrUpdateNavigateList = true); | ||||
| 			var trepo = g.sqlite.GetGuidRepository<TaskBuild>(); | ||||
| 			trepo.Insert(new TaskBuild { | ||||
| 				TaskName = "tt11", | ||||
| 				Builds = new[] { | ||||
| 					new TaskBuildInfo { | ||||
| 						 Level = 1, | ||||
| 						 Name = "t111_11" | ||||
| 					} | ||||
| 				} | ||||
| 			}); | ||||
|  | ||||
| 			var ttdkdkd = trepo.Select.Where(a => a.Builds.AsSelect().Any()).ToList(); | ||||
|  | ||||
| 			var list1113233 = trepo.Select.ToList(); | ||||
|  | ||||
|  | ||||
| 			var entity = new NewsArticle { | ||||
| 				ArticleId = 1, | ||||
| @@ -223,11 +285,16 @@ namespace FreeSql.Tests { | ||||
| 				ArticleId = 1, | ||||
| 				ChannelId = 1, | ||||
| 			}; | ||||
|  | ||||
| 			g.mysql.Insert(new[] { entity }).ExecuteAffrows(); | ||||
|  | ||||
| 			var sqldddkdk = g.mysql.Update<NewsArticle>(where) | ||||
| 				.SetSource(entity) | ||||
| 				.UpdateColumns(x => new { x.Status, x.CategoryId, x.ArticleTitle }) | ||||
| 				.ToSql(); | ||||
|  | ||||
| 			var sqldddklist = g.mysql.Select<NewsArticle>().Select(a => new NewsArticleDto { }).ToList(); | ||||
|  | ||||
|  | ||||
| 			var sql1111333 = g.mysql.Update<Model2>() | ||||
| 				.SetSource(new Model2 { id = 1, Title = "xxx", Parent_id = 0 }) | ||||
|   | ||||
							
								
								
									
										30
									
								
								FreeSql.sln
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								FreeSql.sln
									
									
									
									
									
								
							| @@ -40,7 +40,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.LazyLoading", "Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj", "{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Provider.MySqlConnector", "Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj", "{D2A41321-5E84-410B-B25C-3AA122D4CA27}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.MySqlConnector", "Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj", "{D2A41321-5E84-410B-B25C-3AA122D4CA27}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.DbContext", "..\FreeSql.DbContext\FreeSql.DbContext\FreeSql.DbContext.csproj", "{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Repository", "..\FreeSql.DbContext\FreeSql.Repository\FreeSql.Repository.csproj", "{D7A9C833-8679-41B3-8258-757A6FB27A0E}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| @@ -220,6 +224,30 @@ Global | ||||
| 		{D2A41321-5E84-410B-B25C-3AA122D4CA27}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{D2A41321-5E84-410B-B25C-3AA122D4CA27}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{D2A41321-5E84-410B-B25C-3AA122D4CA27}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x86.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|   | ||||
| @@ -66,7 +66,7 @@ namespace FreeSql.DataAnnotations { | ||||
| 		/// <summary> | ||||
| 		/// 数据库默认值 | ||||
| 		/// </summary> | ||||
| 		public object DbDefautValue { get; set; } | ||||
| 		public object DbDefautValue { get; internal set; } | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 类型映射,比如:可将 enum 属性映射成 typeof(string) | ||||
|   | ||||
							
								
								
									
										16
									
								
								FreeSql/DataAnnotations/NavigateAttribute.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								FreeSql/DataAnnotations/NavigateAttribute.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
|  | ||||
| namespace FreeSql.DataAnnotations { | ||||
| 	public class NavigateAttribute : Attribute { | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// 导航属性,手工绑定 | ||||
| 		/// </summary> | ||||
| 		public string Bind { get; set; } | ||||
|  | ||||
| 		public NavigateAttribute(string bind) { | ||||
| 			this.Bind = bind; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -15,24 +15,26 @@ namespace FreeSql.Extensions.EntityUtil { | ||||
| 		static readonly MethodInfo MethodStringConcat = typeof(string).GetMethod("Concat", new Type[] { typeof(object) }); | ||||
| 		static readonly MethodInfo MethodFreeUtilNewMongodbId = typeof(FreeUtil).GetMethod("NewMongodbId"); | ||||
|  | ||||
| 		static ConcurrentDictionary<DataType, ConcurrentDictionary<Type, Func<object, string>>> _dicGetEntityKeyString = new ConcurrentDictionary<DataType, ConcurrentDictionary<Type, Func<object, string>>>(); | ||||
| 		static ConcurrentDictionary<DataType, ConcurrentDictionary<Type, Func<object, bool, string>>> _dicGetEntityKeyString = new ConcurrentDictionary<DataType, ConcurrentDictionary<Type, Func<object, bool, string>>>(); | ||||
| 		/// <summary> | ||||
| 		/// 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时(当Guid无值时,会生成有序的新值),返回 null | ||||
| 		/// 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null | ||||
| 		/// </summary> | ||||
| 		/// <param name="orm"></param> | ||||
| 		/// <param name="entityType"></param> | ||||
| 		/// <param name="entity"></param> | ||||
| 		/// <param name="genGuid">当Guid无值时,会生成有序的新值</param> | ||||
| 		/// <param name="splitString"></param> | ||||
| 		/// <returns></returns> | ||||
| 		//public static string GetEntityKeyString<TEntity>(this IFreeSql orm, TEntity entity, string splitString = "*|_,[,_|*") => GetEntityKeyString(orm, typeof(TEntity), entity, splitString); | ||||
| 		public static string GetEntityKeyString(this IFreeSql orm, Type entityType, object entity, string splitString = "*|_,[,_|*") { | ||||
| 		public static string GetEntityKeyString(this IFreeSql orm, Type entityType, object entity, bool genGuid, string splitString = "*|_,[,_|*") { | ||||
| 			if (entity == null) return null; | ||||
| 			if (entityType == null) entityType = entity.GetType(); | ||||
| 			var func = _dicGetEntityKeyString.GetOrAdd(orm.Ado.DataType, dt => new ConcurrentDictionary<Type, Func<object, string>>()).GetOrAdd(entityType, t => { | ||||
| 			var func = _dicGetEntityKeyString.GetOrAdd(orm.Ado.DataType, dt => new ConcurrentDictionary<Type, Func<object, bool, string>>()).GetOrAdd(entityType, t => { | ||||
| 				var _table = orm.CodeFirst.GetTableByEntity(t); | ||||
| 				var pks = _table.Primarys; | ||||
| 				var returnTarget = Expression.Label(typeof(string)); | ||||
| 				var parm1 = Expression.Parameter(typeof(object)); | ||||
| 				var parm2 = Expression.Parameter(typeof(bool)); | ||||
| 				var var1Parm = Expression.Variable(t); | ||||
| 				var var2Sb = Expression.Variable(typeof(StringBuilder)); | ||||
| 				var var3IsNull = Expression.Variable(typeof(bool)); | ||||
| @@ -84,7 +86,10 @@ namespace FreeSql.Extensions.EntityUtil { | ||||
| 								Expression.IsFalse(var3IsNull), | ||||
| 								Expression.IfThenElse( | ||||
| 									Expression.Equal(Expression.MakeMemberAccess(var1Parm, _table.Properties[pks[a].CsName]), Expression.Default(pks[a].CsType)), | ||||
| 									expthen, | ||||
| 									Expression.IfThen( | ||||
| 										Expression.IsTrue(parm2), | ||||
| 										expthen | ||||
| 									), | ||||
| 									Expression.Block( | ||||
| 										new Expression[]{ | ||||
| 											a > 0 ? Expression.Call(var2Sb, MethodStringBuilderAppend, Expression.Constant(splitString)) : null, | ||||
| @@ -119,9 +124,9 @@ namespace FreeSql.Extensions.EntityUtil { | ||||
| 					) | ||||
| 				); | ||||
| 				exps.Add(Expression.Label(returnTarget, Expression.Default(typeof(string)))); | ||||
| 				return Expression.Lambda<Func<object, string>>(Expression.Block(new[] { var1Parm, var2Sb, var3IsNull }, exps), new[] { parm1 }).Compile(); | ||||
| 				return Expression.Lambda<Func<object, bool, string>>(Expression.Block(new[] { var1Parm, var2Sb, var3IsNull }, exps), new[] { parm1, parm2 }).Compile(); | ||||
| 			}); | ||||
| 			return func(entity); | ||||
| 			return func(entity, genGuid); | ||||
| 		} | ||||
| 		static ConcurrentDictionary<DataType, ConcurrentDictionary<Type, Func<object, object[]>>> _dicGetEntityKeyValues = new ConcurrentDictionary<DataType, ConcurrentDictionary<Type, Func<object, object[]>>>(); | ||||
| 		/// <summary> | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>netstandard2.0;net45</TargetFrameworks> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<Version>0.6.4</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> | ||||
|   | ||||
| @@ -113,6 +113,11 @@ | ||||
|             <param name="type"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|         <member name="P:FreeSql.DataAnnotations.NavigateAttribute.Bind"> | ||||
|             <summary> | ||||
|             导航属性,手工绑定 | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="P:FreeSql.DataAnnotations.TableAttribute.Name"> | ||||
|             <summary> | ||||
|             数据库表名 | ||||
| @@ -288,13 +293,14 @@ | ||||
|             枚举项 | ||||
|             </summary> | ||||
|         </member> | ||||
|         <member name="M:FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetEntityKeyString(IFreeSql,System.Type,System.Object,System.String)"> | ||||
|         <member name="M:FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetEntityKeyString(IFreeSql,System.Type,System.Object,System.Boolean,System.String)"> | ||||
|             <summary> | ||||
|             获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时(当Guid无值时,会生成有序的新值),返回 null | ||||
|             获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null | ||||
|             </summary> | ||||
|             <param name="orm"></param> | ||||
|             <param name="entityType"></param> | ||||
|             <param name="entity"></param> | ||||
|             <param name="genGuid">当Guid无值时,会生成有序的新值</param> | ||||
|             <param name="splitString"></param> | ||||
|             <returns></returns> | ||||
|         </member> | ||||
|   | ||||
| @@ -500,7 +500,7 @@ namespace FreeSql.Internal { | ||||
| 															if (asSelectParentExp != null) { | ||||
| 																var testExecuteExp = asSelectParentExp; | ||||
| 																if (asSelectParentExp.NodeType == ExpressionType.Parameter) //执行leftjoin关联 | ||||
| 																	testExecuteExp = Expression.Property(testExecuteExp, _common.GetTableByEntity(asSelectParentExp.Type).Properties.First().Value); | ||||
| 																	testExecuteExp = Expression.Property(testExecuteExp, _common.GetTableByEntity(asSelectParentExp.Type).ColumnsByCs.First().Key); | ||||
| 																var tsc2 = tsc.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(new List<SelectColumnInfo>(), tsc.getSelectGroupingMapString, SelectTableInfoType.LeftJoin); | ||||
| 																tsc2.isDisableDiyParse = true; | ||||
| 																tsc2.style = ExpressionStyle.AsSelect; | ||||
| @@ -553,6 +553,10 @@ namespace FreeSql.Internal { | ||||
| 							} | ||||
| 							if (fsql != null) { | ||||
| 								if (asSelectParentExp != null) { //执行 asSelect() 的关联,OneToMany,ManyToMany | ||||
| 									if (fsqltables[0].Parameter == null) { | ||||
| 										fsqltables[0].Alias = $"tb_{fsqltables.Count}"; | ||||
| 										fsqltables[0].Parameter = Expression.Parameter(asSelectEntityType, fsqltables[0].Alias); | ||||
| 									} | ||||
| 									var fsqlWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(asSelectEntityType, asSelectEntityType3 => | ||||
| 										typeof(ISelect<>).MakeGenericType(asSelectEntityType3).GetMethod("Where", new[] { | ||||
| 											typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(asSelectEntityType3, typeof(bool))) | ||||
|   | ||||
							
								
								
									
										75
									
								
								FreeSql/Internal/CommonProvider/CodeFirstProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								FreeSql/Internal/CommonProvider/CodeFirstProvider.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| using FreeSql.DataAnnotations; | ||||
| using FreeSql.Extensions.EntityUtil; | ||||
| using FreeSql.Internal.Model; | ||||
| using System; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | ||||
| using System.Data; | ||||
| using System.Data.Common; | ||||
| using System.Linq; | ||||
| using System.Linq.Expressions; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FreeSql.Internal.CommonProvider { | ||||
|  | ||||
| 	public abstract partial class CodeFirstProvider : ICodeFirst { | ||||
|  | ||||
| 		protected IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| 		public CodeFirstProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { | ||||
| 			_orm = orm; | ||||
| 			_commonUtils = commonUtils; | ||||
| 			_commonExpression = commonExpression; | ||||
| 		} | ||||
|  | ||||
| 		public bool IsAutoSyncStructure { get; set; } = false; | ||||
| 		public bool IsSyncStructureToLower { get; set; } = false; | ||||
| 		public bool IsSyncStructureToUpper { get; set; } = false; | ||||
| 		public bool IsConfigEntityFromDbFirst { get; set; } = false; | ||||
| 		public bool IsNoneCommandParameter { get; set; } = false; | ||||
| 		public bool IsLazyLoading { get; set; } = false; | ||||
|  | ||||
| 		public abstract (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type); | ||||
|  | ||||
| 		public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity); | ||||
| 		public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity); | ||||
| 		public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); | ||||
| 		public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); | ||||
|  | ||||
| 		public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity)); | ||||
| 		public abstract string GetComparisonDDLStatements(params Type[] entityTypes); | ||||
|  | ||||
| 		static object syncStructureLock = new object(); | ||||
| 		internal ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>(); | ||||
| 		public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity)); | ||||
| 		public bool SyncStructure(params Type[] entityTypes) { | ||||
| 			if (entityTypes == null) return true; | ||||
| 			var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); | ||||
| 			if (syncTypes.Any() == false) return true; | ||||
| 			var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); | ||||
| 			_orm.Aop.SyncStructureBefore?.Invoke(this, before); | ||||
| 			Exception exception = null; | ||||
| 			string ddl = null; | ||||
| 			try { | ||||
| 				lock (syncStructureLock) { | ||||
| 					ddl = this.GetComparisonDDLStatements(syncTypes); | ||||
| 					if (string.IsNullOrEmpty(ddl)) { | ||||
| 						foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 						return true; | ||||
| 					} | ||||
| 					var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); | ||||
| 					foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 					return affrows > 0; | ||||
| 				} | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); | ||||
| 				_orm.Aop.SyncStructureAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -159,6 +159,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			if (typeof(TReturn) == typeof(T1)) return this as ISelect<TReturn>; | ||||
| 			_tables[0].Parameter = select.Parameters[0]; | ||||
| 			_selectExpression = select.Body; | ||||
| 			(_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TReturn).FullName, true); | ||||
| 			var ret = _orm.Select<TReturn>(); | ||||
| 			Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null); | ||||
| 			return ret; | ||||
| @@ -172,6 +173,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			), SelectTableInfoType.InnerJoin); | ||||
| 			if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>; | ||||
| 			_selectExpression = resultSelector.Body; | ||||
| 			(_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TResult).FullName, true); | ||||
| 			var ret = _orm.Select<TResult>() as Select1Provider<TResult>; | ||||
| 			Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null); | ||||
| 			return ret; | ||||
| @@ -185,6 +187,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			), SelectTableInfoType.InnerJoin); | ||||
| 			if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>; | ||||
| 			_selectExpression = resultSelector.Body; | ||||
| 			(_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TResult).FullName, true); | ||||
| 			var ret = _orm.Select<TResult>() as Select1Provider<TResult>; | ||||
| 			Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null); | ||||
| 			return ret; | ||||
| @@ -211,6 +214,7 @@ namespace FreeSql.Internal.CommonProvider { | ||||
| 			} | ||||
| 			if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>; | ||||
| 			_selectExpression = resultSelector.Body; | ||||
| 			(_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TResult).FullName, true); | ||||
| 			var ret = _orm.Select<TResult>() as Select1Provider<TResult>; | ||||
| 			Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null); | ||||
| 			return ret; | ||||
|   | ||||
| @@ -231,6 +231,7 @@ namespace FreeSql.Internal { | ||||
| 					$"{pnv.PropertyType.Namespace}.{pnv.PropertyType.Name.Remove(pnv.PropertyType.Name.IndexOf('`'))}<{string.Join(", ", pnv.PropertyType.GenericTypeArguments.Select(a => a.IsNested ? $"{a.DeclaringType.Namespace}.{a.DeclaringType.Name}.{a.Name}" : $"{a.Namespace}.{a.Name}"))}>" : | ||||
| 					(pnv.PropertyType.IsNested ? $"{pnv.PropertyType.DeclaringType.Namespace}.{pnv.PropertyType.DeclaringType.Name}.{pnv.PropertyType.Name}" : $"{pnv.PropertyType.Namespace}.{pnv.PropertyType.Name}"); | ||||
|  | ||||
| 				var pnvBind = pnv.GetCustomAttribute<NavigateAttribute>()?.Bind.Split(',').Select(a => a.Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray(); | ||||
| 				var nvref = new TableRef(); | ||||
| 				nvref.Property = pnv; | ||||
|  | ||||
| @@ -241,7 +242,7 @@ namespace FreeSql.Internal { | ||||
| 					if (trytb.Primarys.Any() == false) { | ||||
| 						nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {trytbTypeName} 缺少主键标识,[Column(IsPrimary = true)]"); | ||||
| 						trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 						if (isLazy) throw nvref.Exception; | ||||
| 						//if (isLazy) throw nvref.Exception; | ||||
| 						continue; | ||||
| 					} | ||||
|  | ||||
| @@ -259,7 +260,7 @@ namespace FreeSql.Internal { | ||||
| 						if (tbref.Primarys.Any() == false) { | ||||
| 							nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {tbrefTypeName} 缺少主键标识,[Column(IsPrimary = true)]"); | ||||
| 							trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 							if (isLazy) throw nvref.Exception; | ||||
| 							//if (isLazy) throw nvref.Exception; | ||||
| 							continue; | ||||
| 						} | ||||
|  | ||||
| @@ -376,14 +377,14 @@ namespace FreeSql.Internal { | ||||
| 							if (trycol != null && trycol.CsType.NullableTypeOrThis() != trytb.Primarys[a].CsType) { | ||||
| 								nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{tbmid.CsName}.{trycol.CsName} 和 {trytb.CsName}.{trytb.Primarys[a].CsName} 类型不一致"); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								if (isLazy) throw nvref.Exception; | ||||
| 								continue; | ||||
| 								//if (isLazy) throw nvref.Exception; | ||||
| 								break; | ||||
| 							} | ||||
| 							if (trycol == null) { | ||||
| 								nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbmid.CsName} 中没有找到对应的字段,如:{midTypePropsTrytb.Name}{findtrytbPkCsName}、{midTypePropsTrytb.Name}_{findtrytbPkCsName}"); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								if (isLazy) throw nvref.Exception; | ||||
| 								continue; | ||||
| 								//if (isLazy) throw nvref.Exception; | ||||
| 								break; | ||||
| 							} | ||||
|  | ||||
| 							nvref.Columns.Add(trytb.Primarys[a]); | ||||
| @@ -397,34 +398,36 @@ namespace FreeSql.Internal { | ||||
| 							} | ||||
| 						} | ||||
|  | ||||
| 						var midTypePropsTbref = tbmid.Properties.Where(a => a.Value.PropertyType == tbref.Type).FirstOrDefault().Value; | ||||
| 						for (var a = 0; a < tbref.Primarys.Length; a++) { | ||||
| 							var findtbrefPkCsName = tbref.Primarys[a].CsName.TrimStart('_'); | ||||
| 							if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(tbref.Type.Name.Length).TrimStart('_'); | ||||
| 							if (tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}{findtbrefPkCsName}", out var trycol) == false && //骆峰命名 | ||||
| 								tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}_{findtbrefPkCsName}", out trycol) == false //下划线命名 | ||||
| 								) { | ||||
| 						if (nvref.Exception == null) { | ||||
| 							var midTypePropsTbref = tbmid.Properties.Where(a => a.Value.PropertyType == tbref.Type).FirstOrDefault().Value; | ||||
| 							for (var a = 0; a < tbref.Primarys.Length; a++) { | ||||
| 								var findtbrefPkCsName = tbref.Primarys[a].CsName.TrimStart('_'); | ||||
| 								if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(tbref.Type.Name.Length).TrimStart('_'); | ||||
| 								if (tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}{findtbrefPkCsName}", out var trycol) == false && //骆峰命名 | ||||
| 									tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}_{findtbrefPkCsName}", out trycol) == false //下划线命名 | ||||
| 									) { | ||||
|  | ||||
| 							} | ||||
| 							if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { | ||||
| 								nvref.Exception = new Exception($"【ManyToMany】导航属性 {tbrefTypeName}.{pnv.Name} 解析错误,{tbmid.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								if (isLazy) throw nvref.Exception; | ||||
| 								continue; | ||||
| 							} | ||||
| 							if (trycol == null) { | ||||
| 								nvref.Exception = new Exception($"【ManyToMany】导航属性 {tbrefTypeName}.{pnv.Name} 在 {tbmid.CsName} 中没有找到对应的字段,如:{midTypePropsTbref.Name}{findtbrefPkCsName}、{midTypePropsTbref.Name}_{findtbrefPkCsName}"); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								if (isLazy) throw nvref.Exception; | ||||
| 								continue; | ||||
| 							} | ||||
| 								} | ||||
| 								if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { | ||||
| 									nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{tbmid.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); | ||||
| 									trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 									//if (isLazy) throw nvref.Exception; | ||||
| 									break; | ||||
| 								} | ||||
| 								if (trycol == null) { | ||||
| 									nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbmid.CsName} 中没有找到对应的字段,如:{midTypePropsTbref.Name}{findtbrefPkCsName}、{midTypePropsTbref.Name}_{findtbrefPkCsName}"); | ||||
| 									trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 									//if (isLazy) throw nvref.Exception; | ||||
| 									break; | ||||
| 								} | ||||
|  | ||||
| 							nvref.RefColumns.Add(tbref.Primarys[a]); | ||||
| 							nvref.MiddleColumns.Add(trycol); | ||||
| 							if (tbmid.Primarys.Any() == false) | ||||
| 								trycol.Attribute.IsPrimary = true; | ||||
| 								nvref.RefColumns.Add(tbref.Primarys[a]); | ||||
| 								nvref.MiddleColumns.Add(trycol); | ||||
| 								if (tbmid.Primarys.Any() == false) | ||||
| 									trycol.Attribute.IsPrimary = true; | ||||
|  | ||||
| 							if (isLazy) lmbdWhere.Append(" && b.").Append(trycol.CsName).Append(" == a.").Append(tbref.Primarys[a].CsName); | ||||
| 								if (isLazy) lmbdWhere.Append(" && b.").Append(trycol.CsName).Append(" == a.").Append(tbref.Primarys[a].CsName); | ||||
| 							} | ||||
| 						} | ||||
| 						if (nvref.Columns.Count > 0 && nvref.RefColumns.Count > 0) { | ||||
| 							nvref.RefMiddleEntityType = tbmid.Type; | ||||
| @@ -441,12 +444,17 @@ namespace FreeSql.Internal { | ||||
| 									.Append("	public override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {"); | ||||
| 							if (vp.Item2) { //get 重写 | ||||
| 								cscode.Append("		get {\r\n") | ||||
| 									.Append("			if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {") | ||||
| 									.Append("				base.").Append(pnv.Name).Append(" = __fsql_orm__.Select<").Append(propElementType.IsNested ? $"{propElementType.DeclaringType.Namespace}.{propElementType.DeclaringType.Name}.{propElementType.Name}" : $"{propElementType.Namespace}.{propElementType.Name}") | ||||
| 									.Append(">().Where(a => __fsql_orm__.Select<").Append(tbmid.Type.IsNested ? $"{tbmid.Type.DeclaringType.Namespace}.{tbmid.Type.DeclaringType.Name}.{tbmid.Type.Name}" : $"{tbmid.Type.Namespace}.{tbmid.Type.Name}") | ||||
| 									.Append(">().Where(b => ").Append(lmbdWhere.ToString()).AppendLine(").Any()).ToList();"); | ||||
| 								cscode.Append("				__lazy__").Append(pnv.Name).AppendLine(" = true;") | ||||
| 									.Append("			}\r\n") | ||||
| 									.Append("			if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {"); | ||||
|  | ||||
| 								if (nvref.Exception == null) | ||||
| 									cscode.Append("				base.").Append(pnv.Name).Append(" = __fsql_orm__.Select<").Append(propElementType.IsNested ? $"{propElementType.DeclaringType.Namespace}.{propElementType.DeclaringType.Name}.{propElementType.Name}" : $"{propElementType.Namespace}.{propElementType.Name}") | ||||
| 										.Append(">().Where(a => __fsql_orm__.Select<").Append(tbmid.Type.IsNested ? $"{tbmid.Type.DeclaringType.Namespace}.{tbmid.Type.DeclaringType.Name}.{tbmid.Type.Name}" : $"{tbmid.Type.Namespace}.{tbmid.Type.Name}") | ||||
| 										.Append(">().Where(b => ").Append(lmbdWhere.ToString()).AppendLine(").Any()).ToList();") | ||||
| 										.Append("				__lazy__").Append(pnv.Name).AppendLine(" = true;"); | ||||
| 								else | ||||
| 									cscode.Append("				throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");"); | ||||
|  | ||||
| 								cscode.Append("			}\r\n") | ||||
| 									.Append("			return base.").Append(pnv.Name).AppendLine(";") | ||||
| 									.Append("		}\r\n"); | ||||
| 							} | ||||
| @@ -456,16 +464,39 @@ namespace FreeSql.Internal { | ||||
| 							cscode.AppendLine("	}"); | ||||
| 						} | ||||
| 					} else { //One To Many | ||||
| 						List<ColumnInfo> bindColumns = new List<ColumnInfo>(); | ||||
| 						if (pnvBind != null) { | ||||
| 							foreach(var bi in pnvBind) { | ||||
| 								if (tbref.ColumnsByCs.TryGetValue(bi, out var trybindcol) == false) { | ||||
| 									nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,在 {tbrefTypeName} 未找到属性:{bi}"); | ||||
| 									trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 									//if (isLazy) throw nvref.Exception; | ||||
| 									break; | ||||
| 								} | ||||
| 								bindColumns.Add(trybindcol); | ||||
| 							} | ||||
| 						} | ||||
|  | ||||
| 						PropertyInfo refprop = null; | ||||
| 						var refcols = tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type); | ||||
| 						var refprop = refcols.Count() == 1 ? refcols.First().Value : null; | ||||
| 						refprop = refcols.Count() == 1 ? refcols.First().Value : null; | ||||
| 						var lmbdWhere = isLazy ? new StringBuilder() : null; | ||||
| 						for (var a = 0; a < trytb.Primarys.Length; a++) { | ||||
|  | ||||
| 						if (nvref.Exception == null && bindColumns.Any() && bindColumns.Count != trytb.Primarys.Length) { | ||||
| 							nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] Bind 数目({bindColumns.Count}) 与 内部主键数目({trytb.Primarys.Length}) 不相同"); | ||||
| 							trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 							//if (isLazy) throw nvref.Exception; | ||||
| 						} | ||||
| 						for (var a = 0; nvref.Exception == null && a < trytb.Primarys.Length; a++) { | ||||
| 							var findtrytbPkCsName = trytb.Primarys[a].CsName.TrimStart('_'); | ||||
| 							if (findtrytbPkCsName.StartsWith(trytb.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtrytbPkCsName = findtrytbPkCsName.Substring(trytb.Type.Name.Length).TrimStart('_'); | ||||
| 							var findtrytb = pnv.Name; | ||||
| 							if (findtrytb.EndsWith(tbref.CsName + "s")) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1); | ||||
| 							findtrytb += trytb.CsName; | ||||
| 							if (tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out var trycol) == false && //骆峰命名 | ||||
|  | ||||
| 							var trycol = bindColumns.Any() ? bindColumns[a] : null; | ||||
| 							if (trycol == null && | ||||
| 								tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out trycol) == false && //骆峰命名 | ||||
| 								tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtrytbPkCsName}", out trycol) == false //下划线命名 | ||||
| 								) { | ||||
| 								if (refprop != null && | ||||
| @@ -474,18 +505,18 @@ namespace FreeSql.Internal { | ||||
| 									{ | ||||
|  | ||||
| 								} | ||||
| 								if (trycol != null && trycol.CsType.NullableTypeOrThis() != trytb.Primarys[a].CsType) { | ||||
| 									nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trytb.Primarys[a].CsName} 和 {tbref.CsName}.{trycol.CsName} 类型不一致"); | ||||
| 									trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 									//if (isLazy) throw nvref.Exception; | ||||
| 									continue; | ||||
| 								} | ||||
| 								if (trycol == null) { | ||||
| 									nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbref.CsName} 中没有找到对应的字段,如:{findtrytb}{findtrytbPkCsName}、{findtrytb}_{findtrytbPkCsName}" + (refprop == null ? "" : $"、{refprop.Name}{findtrytbPkCsName}、{refprop.Name}_{findtrytbPkCsName}")); | ||||
| 									trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 									//if (isLazy) throw nvref.Exception; | ||||
| 									continue; | ||||
| 								} | ||||
| 							} | ||||
| 							if (trycol != null && trycol.CsType.NullableTypeOrThis() != trytb.Primarys[a].CsType) { | ||||
| 								nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trytb.Primarys[a].CsName} 和 {tbref.CsName}.{trycol.CsName} 类型不一致"); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								//if (isLazy) throw nvref.Exception; | ||||
| 								break; | ||||
| 							} | ||||
| 							if (trycol == null) { | ||||
| 								nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbref.CsName} 中没有找到对应的字段,如:{findtrytb}{findtrytbPkCsName}、{findtrytb}_{findtrytbPkCsName}" + (refprop == null ? "" : $"、{refprop.Name}{findtrytbPkCsName}、{refprop.Name}_{findtrytbPkCsName}")); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								//if (isLazy) throw nvref.Exception; | ||||
| 								break; | ||||
| 							} | ||||
|  | ||||
| 							nvref.Columns.Add(trytb.Primarys[a]); | ||||
| @@ -545,20 +576,42 @@ namespace FreeSql.Internal { | ||||
| 					if (tbref.Primarys.Any() == false) { | ||||
| 						nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {propTypeName} 缺少主键标识,[Column(IsPrimary = true)]"); | ||||
| 						trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 						if (isLazy) throw nvref.Exception; | ||||
| 						continue; | ||||
| 						//if (isLazy) throw nvref.Exception; | ||||
| 					} | ||||
| 					var tbrefTypeName = tbref.Type.IsNested ? $"{tbref.Type.DeclaringType.Namespace}.{tbref.Type.DeclaringType.Name}.{tbref.Type.Name}" : $"{tbref.Type.Namespace}.{tbref.Type.Name}"; | ||||
| 					var isOnoToOne = pnv.PropertyType != trytb.Type && | ||||
| 						tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type).Any() && | ||||
| 						tbref.Primarys.Length == trytb.Primarys.Length && | ||||
| 						string.Join(",", tbref.Primarys.Select(a => a.CsType.FullName).OrderBy(a => a)) == string.Join(",", trytb.Primarys.Select(a => a.CsType.FullName).OrderBy(a => a)); | ||||
|  | ||||
| 					List<ColumnInfo> bindColumns = new List<ColumnInfo>(); | ||||
| 					if (pnvBind != null) { | ||||
| 						foreach(var bi in pnvBind) { | ||||
| 							if (trytb.ColumnsByCs.TryGetValue(bi, out var trybindcol) == false) { | ||||
| 								nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,在 {trytbTypeName} 未找到属性:{bi}"); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								//if (isLazy) throw nvref.Exception; | ||||
| 								break; | ||||
| 							} | ||||
| 							bindColumns.Add(trybindcol); | ||||
| 						} | ||||
| 					} | ||||
| 					var lmbdWhere = new StringBuilder(); | ||||
| 					for (var a = 0; a < tbref.Primarys.Length; a++) { | ||||
|  | ||||
| 					if (nvref.Exception == null && bindColumns.Any() && bindColumns.Count != tbref.Primarys.Length) { | ||||
| 						nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] Bind 数目({bindColumns.Count}) 与 外部主键数目({tbref.Primarys.Length}) 不相同"); | ||||
| 						trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 						//if (isLazy) throw nvref.Exception; | ||||
| 					} | ||||
| 					for (var a = 0; nvref.Exception == null && a < tbref.Primarys.Length; a++) { | ||||
| 						var findtbrefPkCsName = tbref.Primarys[a].CsName.TrimStart('_'); | ||||
| 						if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(tbref.Type.Name.Length).TrimStart('_'); | ||||
| 						if (trytb.ColumnsByCs.TryGetValue($"{pnv.Name}{findtbrefPkCsName}", out var trycol) == false && //骆峰命名 | ||||
|  | ||||
| 						var trycol = bindColumns.Any() ? bindColumns[a] : null; | ||||
| 						if (trycol == null && | ||||
| 							trytb.ColumnsByCs.TryGetValue($"{pnv.Name}{findtbrefPkCsName}", out trycol) == false && //骆峰命名 | ||||
| 							trytb.ColumnsByCs.TryGetValue($"{pnv.Name}_{findtbrefPkCsName}", out trycol) == false && //下划线命名 | ||||
| 							//tbref.Primarys.Length == 1 && | ||||
| 																													 //tbref.Primarys.Length == 1 && | ||||
| 							trytb.ColumnsByCs.TryGetValue($"{pnv.Name}_Id", out trycol) == false && | ||||
| 							trytb.ColumnsByCs.TryGetValue($"{pnv.Name}Id", out trycol) == false | ||||
| 							) { | ||||
| @@ -579,19 +632,18 @@ namespace FreeSql.Internal { | ||||
| 									} | ||||
| 								} | ||||
| 							} | ||||
| 							if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { | ||||
| 								nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); | ||||
| 								trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 								if (isLazy) throw nvref.Exception; | ||||
| 								continue; | ||||
| 							} | ||||
| 						} | ||||
|  | ||||
| 						if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { | ||||
| 							nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); | ||||
| 							trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 							//if (isLazy) throw nvref.Exception; | ||||
| 							break; | ||||
| 						} | ||||
| 						if (trycol == null) { | ||||
| 							nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 没有找到对应的字段,如:{pnv.Name}{findtbrefPkCsName}、{pnv.Name}_{findtbrefPkCsName}"); | ||||
| 							trytb.AddOrUpdateTableRef(pnv.Name, nvref); | ||||
| 							//if (isLazy) throw nvref.Exception; | ||||
| 							continue; | ||||
| 							break; | ||||
| 						} | ||||
|  | ||||
| 						nvref.Columns.Add(trycol); | ||||
| @@ -658,7 +710,7 @@ namespace FreeSql.Internal { | ||||
| 		} | ||||
| 		static Lazy<MethodInfo> MethodLazyLoadingComplier = new Lazy<MethodInfo>(() => { | ||||
| 			var type = Type.GetType("FreeSql.Extensions.LazyLoading.LazyLoadingComplier,FreeSql.Extensions.LazyLoading"); | ||||
| 			return type.GetMethod("CompileCode"); | ||||
| 			return type?.GetMethod("CompileCode"); | ||||
| 		}); | ||||
|  | ||||
| 		public static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) { | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>netstandard2.0;net452</TargetFrameworks> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<Version>0.6.4</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 MySql 5.6</Description> | ||||
|   | ||||
| @@ -13,22 +13,9 @@ using System.Text.RegularExpressions; | ||||
|  | ||||
| namespace FreeSql.MySql { | ||||
|  | ||||
| 	class MySqlCodeFirst : ICodeFirst { | ||||
| 		IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| 		public MySqlCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { | ||||
| 			_orm = orm; | ||||
| 			_commonUtils = commonUtils; | ||||
| 			_commonExpression = commonExpression; | ||||
| 		} | ||||
| 	class MySqlCodeFirst : Internal.CommonProvider.CodeFirstProvider { | ||||
|  | ||||
| 		public bool IsAutoSyncStructure { get; set; } = false; | ||||
| 		public bool IsSyncStructureToLower { get; set; } = false; | ||||
| 		public bool IsSyncStructureToUpper { get; set; } = false; | ||||
| 		public bool IsConfigEntityFromDbFirst { get; set; } = false; | ||||
| 		public bool IsNoneCommandParameter { get; set; } = false; | ||||
| 		public bool IsLazyLoading { get; set; } = false; | ||||
| 		public MySqlCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } | ||||
|  | ||||
| 		static object _dicCsToDbLock = new object(); | ||||
| 		static Dictionary<string, (MySqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (MySqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() { | ||||
| @@ -64,7 +51,7 @@ namespace FreeSql.MySql { | ||||
| 				{ typeof(MygisMultiPolygon).FullName,  (MySqlDbType.Geometry, "multipolygon", "multipolygon", false, null, new MygisMultiPolygon(new[]{new MygisPolygon(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}}),new MygisPolygon(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}})})) }, | ||||
| 			}; | ||||
|  | ||||
| 		public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 		public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 			if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); | ||||
| 			if (type.IsArray) return null; | ||||
| 			var enumType = type.IsEnum ? type : null; | ||||
| @@ -85,8 +72,7 @@ namespace FreeSql.MySql { | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity)); | ||||
| 		public string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 		public override string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 			var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); | ||||
| 			var database = conn.Value.Database; | ||||
| 			Func<string, string, object> ExecuteScalar = (db, sql) => { | ||||
| @@ -205,6 +191,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); | ||||
| 							} | ||||
| 							//添加列 | ||||
| 							sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType); | ||||
| 							if (tbcol.Attribute.IsNullable == false) sbalter.Append(" DEFAULT ").Append(_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)); | ||||
| 							if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")"); | ||||
| 							sbalter.Append(";\r\n"); | ||||
| 						} | ||||
| @@ -286,40 +273,5 @@ where a.constraint_schema IN ({0}) and a.table_name IN ({1})", tboldname ?? tbna | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		static object syncStructureLock = new object(); | ||||
| 		ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>(); | ||||
| 		public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity)); | ||||
| 		public bool SyncStructure(params Type[] entityTypes) { | ||||
| 			if (entityTypes == null) return true; | ||||
| 			var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); | ||||
| 			if (syncTypes.Any() == false) return true; | ||||
| 			var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); | ||||
| 			_orm.Aop.SyncStructureBefore?.Invoke(this, before); | ||||
| 			Exception exception = null; | ||||
| 			string ddl = null; | ||||
| 			try { | ||||
| 				lock (syncStructureLock) { | ||||
| 					ddl = this.GetComparisonDDLStatements(syncTypes); | ||||
| 					if (string.IsNullOrEmpty(ddl)) { | ||||
| 						foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 						return true; | ||||
| 					} | ||||
| 					var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); | ||||
| 					foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 					return affrows > 0; | ||||
| 				} | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); | ||||
| 				_orm.Aop.SyncStructureAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 		} | ||||
| 		public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity); | ||||
| 		public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity); | ||||
| 		public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); | ||||
| 		public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); | ||||
| 	} | ||||
| } | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>netstandard2.0;net45</TargetFrameworks> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<Version>0.6.4</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 MySql 5.6</Description> | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>netstandard2.0;net45</TargetFrameworks> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<Version>0.6.4</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 Oracle 11</Description> | ||||
|   | ||||
| @@ -13,22 +13,9 @@ using System.Text.RegularExpressions; | ||||
|  | ||||
| namespace FreeSql.Oracle { | ||||
|  | ||||
| 	class OracleCodeFirst : ICodeFirst { | ||||
| 		IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| 		public OracleCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { | ||||
| 			_orm = orm; | ||||
| 			_commonUtils = commonUtils; | ||||
| 			_commonExpression = commonExpression; | ||||
| 		} | ||||
| 	class OracleCodeFirst : Internal.CommonProvider.CodeFirstProvider { | ||||
|  | ||||
| 		public bool IsAutoSyncStructure { get; set; } = false; | ||||
| 		public bool IsSyncStructureToLower { get; set; } = false; | ||||
| 		public bool IsSyncStructureToUpper { get; set; } = false; | ||||
| 		public bool IsConfigEntityFromDbFirst { get; set; } = false; | ||||
| 		public bool IsNoneCommandParameter { get; set; } = false; | ||||
| 		public bool IsLazyLoading { get; set; } = false; | ||||
| 		public OracleCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } | ||||
|  | ||||
| 		static object _dicCsToDbLock = new object(); | ||||
| 		static Dictionary<string, (OracleDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (OracleDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() { | ||||
| @@ -58,7 +45,7 @@ namespace FreeSql.Oracle { | ||||
| 				{ typeof(Guid).FullName,  (OracleDbType.Char, "char", "char(36 CHAR) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName,  (OracleDbType.Char, "char", "char(36 CHAR) NULL", false, true, null) }, | ||||
| 			}; | ||||
|  | ||||
| 		public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 		public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 			if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); | ||||
| 			if (type.IsArray) return null; | ||||
| 			var enumType = type.IsEnum ? type : null; | ||||
| @@ -78,8 +65,7 @@ namespace FreeSql.Oracle { | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity)); | ||||
| 		public string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 		public override string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 			var userId = (_orm.Ado.MasterPool as OracleConnectionPool).UserId; | ||||
| 			var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列 | ||||
|  | ||||
| @@ -333,40 +319,5 @@ and a.owner in ({0}) and a.table_name in ({1})", tboldname ?? tbname); | ||||
| 				sqlType += $"({data_length})"; | ||||
| 			return sqlType; | ||||
| 		} | ||||
|  | ||||
| 		static object syncStructureLock = new object(); | ||||
| 		ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>(); | ||||
| 		public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity)); | ||||
| 		public bool SyncStructure(params Type[] entityTypes) { | ||||
| 			if (entityTypes == null) return true; | ||||
| 			var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); | ||||
| 			if (syncTypes.Any() == false) return true; | ||||
| 			var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); | ||||
| 			_orm.Aop.SyncStructureBefore?.Invoke(this, before); | ||||
| 			Exception exception = null; | ||||
| 			string ddl = null; | ||||
| 			try { | ||||
| 				lock (syncStructureLock) { | ||||
| 					ddl = this.GetComparisonDDLStatements(syncTypes); | ||||
| 					if (string.IsNullOrEmpty(ddl)) { | ||||
| 						foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 						return true; | ||||
| 					} | ||||
| 					var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); | ||||
| 					foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 					return affrows > 0; | ||||
| 				} | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); | ||||
| 				_orm.Aop.SyncStructureAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 		} | ||||
| 		public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity); | ||||
| 		public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity); | ||||
| 		public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); | ||||
| 		public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); | ||||
| 	} | ||||
| } | ||||
| @@ -58,6 +58,9 @@ namespace FreeSql.Oracle { | ||||
| 				case "interval day to second": | ||||
| 					_dicDbToCs.TryAdd(dbfull, _dicDbToCs["interval day(2) to second(6)"]); | ||||
| 					return OracleDbType.IntervalDS; | ||||
| 				case "date": | ||||
| 					_dicDbToCs.TryAdd(dbfull, _dicDbToCs["date(7)"]); | ||||
| 					return OracleDbType.IntervalDS; | ||||
| 				case "timestamp": | ||||
| 					_dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6)"]); | ||||
| 					return OracleDbType.TimeStamp; | ||||
| @@ -106,6 +109,7 @@ namespace FreeSql.Oracle { | ||||
| 				{ "number(10,2)", ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") }, | ||||
|  | ||||
| 				{ "interval day(2) to second(6)", ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") }, | ||||
| 				{ "date(7)", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, | ||||
| 				{ "timestamp(6)", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, | ||||
| 				{ "timestamp(6) with local time zone", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>netstandard2.0;net45</TargetFrameworks> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<Version>0.6.4</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 PostgreSQL 9.5</Description> | ||||
|   | ||||
| @@ -18,22 +18,9 @@ using System.Text.RegularExpressions; | ||||
|  | ||||
| namespace FreeSql.PostgreSQL { | ||||
|  | ||||
| 	class PostgreSQLCodeFirst : ICodeFirst { | ||||
| 		IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| 		public PostgreSQLCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { | ||||
| 			_orm = orm; | ||||
| 			_commonUtils = commonUtils; | ||||
| 			_commonExpression = commonExpression; | ||||
| 		} | ||||
| 	class PostgreSQLCodeFirst : Internal.CommonProvider.CodeFirstProvider { | ||||
|  | ||||
| 		public bool IsAutoSyncStructure { get; set; } = false; | ||||
| 		public bool IsSyncStructureToLower { get; set; } = false; | ||||
| 		public bool IsSyncStructureToUpper { get; set; } = false; | ||||
| 		public bool IsConfigEntityFromDbFirst { get; set; } = false; | ||||
| 		public bool IsNoneCommandParameter { get; set; } = false; | ||||
| 		public bool IsLazyLoading { get; set; } = false; | ||||
| 		public PostgreSQLCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } | ||||
|  | ||||
| 		static object _dicCsToDbLock = new object(); | ||||
| 		static Dictionary<string, (NpgsqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (NpgsqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() { | ||||
| @@ -94,7 +81,7 @@ namespace FreeSql.PostgreSQL { | ||||
| 				{ typeof(PostgisGeometryCollection).FullName,  (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisGeometryCollection(new[]{new PostgisPoint(0, 0),new PostgisPoint(0, 0) })) }, | ||||
| 			}; | ||||
|  | ||||
| 		public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 		public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 			var isarray = type.FullName != "System.Byte[]" && type.IsArray; | ||||
| 			var elementType = isarray ? type.GetElementType() : type; | ||||
| 			var info = GetDbInfoNoneArray(elementType); | ||||
| @@ -122,9 +109,8 @@ namespace FreeSql.PostgreSQL { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity)); | ||||
| 		public string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 		 | ||||
| 		public override string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 			var sb = new StringBuilder(); | ||||
| 			var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列 | ||||
|  | ||||
| @@ -338,40 +324,5 @@ where pg_namespace.nspname={0} and pg_class.relname={1} and pg_constraint.contyp | ||||
| 			} | ||||
| 			return sb.Length == 0 ? null : sb.ToString(); | ||||
| 		} | ||||
|  | ||||
| 		static object syncStructureLock = new object(); | ||||
| 		ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>(); | ||||
| 		public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity)); | ||||
| 		public bool SyncStructure(params Type[] entityTypes) { | ||||
| 			if (entityTypes == null) return true; | ||||
| 			var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); | ||||
| 			if (syncTypes.Any() == false) return true; | ||||
| 			var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); | ||||
| 			_orm.Aop.SyncStructureBefore?.Invoke(this, before); | ||||
| 			Exception exception = null; | ||||
| 			string ddl = null; | ||||
| 			try { | ||||
| 				lock (syncStructureLock) { | ||||
| 					ddl = this.GetComparisonDDLStatements(syncTypes); | ||||
| 					if (string.IsNullOrEmpty(ddl)) { | ||||
| 						foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 						return true; | ||||
| 					} | ||||
| 					var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); | ||||
| 					foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 					return affrows > 0; | ||||
| 				} | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); | ||||
| 				_orm.Aop.SyncStructureAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 		} | ||||
| 		public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity); | ||||
| 		public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity); | ||||
| 		public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); | ||||
| 		public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); | ||||
| 	} | ||||
| } | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>netstandard2.0;net451</TargetFrameworks> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<Version>0.6.4</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 SqlServer 2005+,并根据版本适配分页方法:row_number 或 offset fetch next</Description> | ||||
|   | ||||
| @@ -12,22 +12,9 @@ using System.Text.RegularExpressions; | ||||
|  | ||||
| namespace FreeSql.SqlServer { | ||||
|  | ||||
| 	class SqlServerCodeFirst : ICodeFirst { | ||||
| 		IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| 		public SqlServerCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { | ||||
| 			_orm = orm; | ||||
| 			_commonUtils = commonUtils; | ||||
| 			_commonExpression = commonExpression; | ||||
| 		} | ||||
|  | ||||
| 		public bool IsAutoSyncStructure { get; set; } = false; | ||||
| 		public bool IsSyncStructureToLower { get; set; } = false; | ||||
| 		public bool IsSyncStructureToUpper { get; set; } = false; | ||||
| 		public bool IsConfigEntityFromDbFirst { get; set; } = false; | ||||
| 		public bool IsNoneCommandParameter { get; set; } = false; | ||||
| 		public bool IsLazyLoading { get; set; } = false; | ||||
| 	class SqlServerCodeFirst : Internal.CommonProvider.CodeFirstProvider { | ||||
| 		 | ||||
| 		public SqlServerCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } | ||||
|  | ||||
| 		static object _dicCsToDbLock = new object(); | ||||
| 		static Dictionary<string, (SqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (SqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() { | ||||
| @@ -57,7 +44,7 @@ namespace FreeSql.SqlServer { | ||||
| 				{ typeof(Guid).FullName,  (SqlDbType.UniqueIdentifier, "uniqueidentifier", "uniqueidentifier NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName,  (SqlDbType.UniqueIdentifier, "uniqueidentifier", "uniqueidentifier", false, true, null) }, | ||||
| 			}; | ||||
|  | ||||
| 		public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 		public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 			if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); | ||||
| 			if (type.IsArray) return null; | ||||
| 			var enumType = type.IsEnum ? type : null; | ||||
| @@ -76,9 +63,8 @@ namespace FreeSql.SqlServer { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity)); | ||||
| 		public string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 		 | ||||
| 		public override string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 			var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); | ||||
| 			var database = conn.Value.Database; | ||||
| 			Func<string, string, object> ExecuteScalar = (db, sql) => { | ||||
| @@ -326,41 +312,5 @@ use " + database, tboldname ?? tbname); | ||||
| 			} | ||||
| 			return ddv; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		static object syncStructureLock = new object(); | ||||
| 		ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>(); | ||||
| 		public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity)); | ||||
| 		public bool SyncStructure(params Type[] entityTypes) { | ||||
| 			if (entityTypes == null) return true; | ||||
| 			var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); | ||||
| 			if (syncTypes.Any() == false) return true; | ||||
| 			var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); | ||||
| 			_orm.Aop.SyncStructureBefore?.Invoke(this, before); | ||||
| 			Exception exception = null; | ||||
| 			string ddl = null; | ||||
| 			try { | ||||
| 				lock (syncStructureLock) { | ||||
| 					ddl = this.GetComparisonDDLStatements(syncTypes); | ||||
| 					if (string.IsNullOrEmpty(ddl)) { | ||||
| 						foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 						return true; | ||||
| 					} | ||||
| 					var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); | ||||
| 					foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 					return affrows > 0; | ||||
| 				} | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); | ||||
| 				_orm.Aop.SyncStructureAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 		} | ||||
| 		public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity); | ||||
| 		public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity); | ||||
| 		public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); | ||||
| 		public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); | ||||
| 	} | ||||
| } | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFrameworks>netstandard2.0;net45</TargetFrameworks> | ||||
| 		<Version>0.6.3</Version> | ||||
| 		<Version>0.6.4</Version> | ||||
| 		<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| 		<Authors>YeXiangQin</Authors> | ||||
| 		<Description>FreeSql 数据库实现,基于 Sqlite 3.0</Description> | ||||
|   | ||||
| @@ -12,22 +12,9 @@ using System.Text.RegularExpressions; | ||||
|  | ||||
| namespace FreeSql.Sqlite { | ||||
|  | ||||
| 	class SqliteCodeFirst : ICodeFirst { | ||||
| 		IFreeSql _orm; | ||||
| 		protected CommonUtils _commonUtils; | ||||
| 		protected CommonExpression _commonExpression; | ||||
| 		public SqliteCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { | ||||
| 			_orm = orm; | ||||
| 			_commonUtils = commonUtils; | ||||
| 			_commonExpression = commonExpression; | ||||
| 		} | ||||
| 	class SqliteCodeFirst : Internal.CommonProvider.CodeFirstProvider { | ||||
|  | ||||
| 		public bool IsAutoSyncStructure { get; set; } = false; | ||||
| 		public bool IsSyncStructureToLower { get; set; } = false; | ||||
| 		public bool IsSyncStructureToUpper { get; set; } = false; | ||||
| 		public bool IsConfigEntityFromDbFirst { get; set; } = false; | ||||
| 		public bool IsNoneCommandParameter { get; set; } = false; | ||||
| 		public bool IsLazyLoading { get; set; } = false; | ||||
| 		public SqliteCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } | ||||
|  | ||||
| 		static object _dicCsToDbLock = new object(); | ||||
| 		static Dictionary<string, (DbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (DbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() { | ||||
| @@ -56,7 +43,7 @@ namespace FreeSql.Sqlite { | ||||
| 				{ typeof(Guid).FullName,  (DbType.Guid, "character", "character(36) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName,  (DbType.Guid, "character", "character(36)", false, true, null) }, | ||||
| 			}; | ||||
|  | ||||
| 		public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 		public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { | ||||
| 			if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); | ||||
| 			if (type.IsArray) return null; | ||||
| 			var enumType = type.IsEnum ? type : null; | ||||
| @@ -75,9 +62,8 @@ namespace FreeSql.Sqlite { | ||||
| 			} | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity)); | ||||
| 		public string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 		 | ||||
| 		public override string GetComparisonDDLStatements(params Type[] entityTypes) { | ||||
| 			var sb = new StringBuilder(); | ||||
| 			var sbDeclare = new StringBuilder(); | ||||
| 			foreach (var entityType in entityTypes) { | ||||
| @@ -250,40 +236,5 @@ namespace FreeSql.Sqlite { | ||||
| 			return sb.Length == 0 ? null : sb.ToString(); | ||||
| 		} | ||||
| 		static Regex _regexUK = new Regex(@"CONSTRAINT\s*""([^""]+)""\s*UNIQUE\s*\(([^\)]+)\)", RegexOptions.IgnoreCase | RegexOptions.Compiled); | ||||
|  | ||||
| 		static object syncStructureLock = new object(); | ||||
| 		ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>(); | ||||
| 		public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity)); | ||||
| 		public bool SyncStructure(params Type[] entityTypes) { | ||||
| 			if (entityTypes == null) return true; | ||||
| 			var syncTypes = entityTypes.Where(a => a.IsAnonymousType() == false && dicSyced.ContainsKey(a.FullName) == false).ToArray(); | ||||
| 			if (syncTypes.Any() == false) return true; | ||||
| 			var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); | ||||
| 			_orm.Aop.SyncStructureBefore?.Invoke(this, before); | ||||
| 			Exception exception = null; | ||||
| 			string ddl = null; | ||||
| 			try { | ||||
| 				lock (syncStructureLock) { | ||||
| 					ddl = this.GetComparisonDDLStatements(syncTypes); | ||||
| 					if (string.IsNullOrEmpty(ddl)) { | ||||
| 						foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 						return true; | ||||
| 					} | ||||
| 					var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); | ||||
| 					foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); | ||||
| 					return affrows > 0; | ||||
| 				} | ||||
| 			} catch (Exception ex) { | ||||
| 				exception = ex; | ||||
| 				throw ex; | ||||
| 			} finally { | ||||
| 				var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); | ||||
| 				_orm.Aop.SyncStructureAfter?.Invoke(this, after); | ||||
| 			} | ||||
| 		} | ||||
| 		public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity); | ||||
| 		public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity); | ||||
| 		public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); | ||||
| 		public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); | ||||
| 	} | ||||
| } | ||||
| @@ -45,7 +45,7 @@ FreeSql 是一个功能强大的 .NETStandard 库,用于对象关系映射程 | ||||
| | FreeSql.Provider.SqlServer | NETStandard2.0、net451 | | ||||
| | FreeSql.Provider.Sqlite | NETStandard2.0、net45 | | ||||
| | FreeSql.Provider.Oracle | NETStandard2.0、net45 | | ||||
| | FreeSql.Extensions.LazyLoading | NETStandard2.0 | | ||||
| | FreeSql.Extensions.LazyLoading | NETStandard2.0、net45 | | ||||
|  | ||||
| # Quick start | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 28810
					28810