mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	update
This commit is contained in:
		
							
								
								
									
										27
									
								
								FreeSql.Tests/Generator/PostgreSQLTemplateGeneratorTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								FreeSql.Tests/Generator/PostgreSQLTemplateGeneratorTest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					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");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -541,7 +541,8 @@ return rTn;");
 | 
				
			|||||||
		#region Complie
 | 
							#region Complie
 | 
				
			||||||
		private static ITemplateOutput Complie(string cscode, string typename) {
 | 
							private static ITemplateOutput Complie(string cscode, string typename) {
 | 
				
			||||||
			var assemly = _compiler.Value.CompileCode(cscode);
 | 
								var assemly = _compiler.Value.CompileCode(cscode);
 | 
				
			||||||
			return assemly.CreateInstance(typename) as ITemplateOutput;
 | 
								var type = assemly.DefinedTypes.Where(a => a.FullName.EndsWith(typename)).FirstOrDefault();
 | 
				
			||||||
 | 
								return Activator.CreateInstance(type) as ITemplateOutput;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		static ConcurrentDictionary<string, (DateTime, object)> _compiler_objs = new ConcurrentDictionary<string, (DateTime, object)>();
 | 
							static ConcurrentDictionary<string, (DateTime, object)> _compiler_objs = new ConcurrentDictionary<string, (DateTime, object)>();
 | 
				
			||||||
		static Lazy<CSScriptLib.RoslynEvaluator> _compiler = new Lazy<CSScriptLib.RoslynEvaluator>(() => {
 | 
							static Lazy<CSScriptLib.RoslynEvaluator> _compiler = new Lazy<CSScriptLib.RoslynEvaluator>(() => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,385 +0,0 @@
 | 
				
			|||||||
using FreeSql.DatabaseModel;
 | 
					 | 
				
			||||||
using FreeSql.Internal;
 | 
					 | 
				
			||||||
using MySql.Data.MySqlClient;
 | 
					 | 
				
			||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Data;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Text.RegularExpressions;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace FreeSql.Oracle {
 | 
					 | 
				
			||||||
	class OracleDbFirst : IDbFirst {
 | 
					 | 
				
			||||||
		IFreeSql _orm;
 | 
					 | 
				
			||||||
		protected CommonUtils _commonUtils;
 | 
					 | 
				
			||||||
		protected CommonExpression _commonExpression;
 | 
					 | 
				
			||||||
		public OracleDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
 | 
					 | 
				
			||||||
			_orm = orm;
 | 
					 | 
				
			||||||
			_commonUtils = commonUtils;
 | 
					 | 
				
			||||||
			_commonExpression = commonExpression;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public int GetDbType(DbColumnInfo column) => (int)GetMySqlDbType(column);
 | 
					 | 
				
			||||||
		MySqlDbType GetMySqlDbType(DbColumnInfo column) {
 | 
					 | 
				
			||||||
			var is_unsigned = column.DbTypeTextFull.ToLower().EndsWith(" unsigned");
 | 
					 | 
				
			||||||
			switch (column.DbTypeText.ToLower()) {
 | 
					 | 
				
			||||||
				case "bit": return MySqlDbType.Bit;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "tinyint": return is_unsigned ? MySqlDbType.UByte : MySqlDbType.Byte;
 | 
					 | 
				
			||||||
				case "smallint": return is_unsigned ? MySqlDbType.UInt16 : MySqlDbType.Int16;
 | 
					 | 
				
			||||||
				case "mediumint": return is_unsigned ? MySqlDbType.UInt24 : MySqlDbType.Int24;
 | 
					 | 
				
			||||||
				case "int": return is_unsigned ? MySqlDbType.UInt32 : MySqlDbType.Int32;
 | 
					 | 
				
			||||||
				case "bigint": return is_unsigned ? MySqlDbType.UInt64 : MySqlDbType.Int64;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "real":
 | 
					 | 
				
			||||||
				case "double": return MySqlDbType.Double;
 | 
					 | 
				
			||||||
				case "float": return MySqlDbType.Float;
 | 
					 | 
				
			||||||
				case "numeric":
 | 
					 | 
				
			||||||
				case "decimal": return MySqlDbType.Decimal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "year": return MySqlDbType.Year;
 | 
					 | 
				
			||||||
				case "time": return MySqlDbType.Time;
 | 
					 | 
				
			||||||
				case "date": return MySqlDbType.Date;
 | 
					 | 
				
			||||||
				case "timestamp": return MySqlDbType.Timestamp;
 | 
					 | 
				
			||||||
				case "datetime": return MySqlDbType.DateTime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "tinyblob": return MySqlDbType.TinyBlob;
 | 
					 | 
				
			||||||
				case "blob": return MySqlDbType.Blob;
 | 
					 | 
				
			||||||
				case "mediumblob": return MySqlDbType.MediumBlob;
 | 
					 | 
				
			||||||
				case "longblob": return MySqlDbType.LongBlob;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "binary": return MySqlDbType.Binary;
 | 
					 | 
				
			||||||
				case "varbinary": return MySqlDbType.VarBinary;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "tinytext": return MySqlDbType.TinyText;
 | 
					 | 
				
			||||||
				case "text": return MySqlDbType.Text;
 | 
					 | 
				
			||||||
				case "mediumtext": return MySqlDbType.MediumText;
 | 
					 | 
				
			||||||
				case "longtext": return MySqlDbType.LongText;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "char": return column.MaxLength == 36 ? MySqlDbType.Guid : MySqlDbType.String;
 | 
					 | 
				
			||||||
				case "varchar": return MySqlDbType.VarChar;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "set": return MySqlDbType.Set;
 | 
					 | 
				
			||||||
				case "enum": return MySqlDbType.Enum;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "point": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "linestring": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "polygon": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "geometry": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "multipoint": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "multilinestring": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "multipolygon": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "geometrycollection": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				default: return MySqlDbType.String;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Bit, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Byte, ("(sbyte?)", "sbyte.Parse({0})", "{0}.ToString()", "sbyte?", typeof(sbyte), typeof(sbyte?), "{0}.Value", "GetByte") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int16, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int24, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int32, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int64, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UByte, ("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt16, ("(ushort?)", "ushort.Parse({0})", "{0}.ToString()", "ushort?", typeof(ushort), typeof(ushort?), "{0}.Value", "GetInt16") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt24, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt32, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt64, ("(ulong?)", "ulong.Parse({0})", "{0}.ToString()", "ulong?", typeof(ulong), typeof(ulong?), "{0}.Value", "GetInt64") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Double, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Float, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Decimal, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Year, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Time, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Timestamp, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.DateTime, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.TinyBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Blob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.MediumBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.LongBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Binary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.VarBinary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.TinyText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.MediumText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.LongText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Guid, ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid?", typeof(Guid), typeof(Guid?), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.String, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.VarString, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Set, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Set", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Enum, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Enum", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Geometry, ("(MygisGeometry)", "MygisGeometry.Parse({0}.Replace(StringifySplit, \"|\"))", "{0}.AsText().Replace(\"|\", StringifySplit)", "MygisGeometry", typeof(MygisGeometry), typeof(MygisGeometry), "{0}", "GetString") },
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
 | 
					 | 
				
			||||||
		public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csParse : null;
 | 
					 | 
				
			||||||
		public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csStringify : null;
 | 
					 | 
				
			||||||
		public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null;
 | 
					 | 
				
			||||||
		public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeInfo : null;
 | 
					 | 
				
			||||||
		public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeValue : null;
 | 
					 | 
				
			||||||
		public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public List<string> GetDatabases() {
 | 
					 | 
				
			||||||
			var sql = @" select username from sys.dba_users";
 | 
					 | 
				
			||||||
			var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public List<DbTableInfo> GetTablesByDatabase(params string[] database) {
 | 
					 | 
				
			||||||
			var loc1 = new List<DbTableInfo>();
 | 
					 | 
				
			||||||
			var loc2 = new Dictionary<string, DbTableInfo>();
 | 
					 | 
				
			||||||
			var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (database == null || database.Any() == false) return loc1;
 | 
					 | 
				
			||||||
			var databaseIn = string.Join(",", database.Select(a => "{0}".FormatMySql(a)));
 | 
					 | 
				
			||||||
			var sql = string.Format(@"
 | 
					 | 
				
			||||||
select 
 | 
					 | 
				
			||||||
concat(a.table_schema, '.', a.table_name) 'id',
 | 
					 | 
				
			||||||
a.table_schema 'schema',
 | 
					 | 
				
			||||||
a.table_name 'table',
 | 
					 | 
				
			||||||
a.table_type 'type'
 | 
					 | 
				
			||||||
from information_schema.tables a
 | 
					 | 
				
			||||||
where a.table_schema in ({0})", databaseIn);
 | 
					 | 
				
			||||||
			var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var loc6 = new List<string>();
 | 
					 | 
				
			||||||
			var loc66 = new List<string>();
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				var table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				var schema = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				var table = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				var type = string.Concat(row[3]) == "VIEW" ? DbTableType.VIEW : DbTableType.TABLE;
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
					schema = "";
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc2.Add(table_id, new DbTableInfo { Id = table_id, Schema = schema, Name = table, Type = type });
 | 
					 | 
				
			||||||
				loc3.Add(table_id, new Dictionary<string, DbColumnInfo>());
 | 
					 | 
				
			||||||
				switch (type) {
 | 
					 | 
				
			||||||
					case DbTableType.TABLE:
 | 
					 | 
				
			||||||
					case DbTableType.VIEW:
 | 
					 | 
				
			||||||
						loc6.Add(table.Replace("'", "''"));
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					case DbTableType.StoreProcedure:
 | 
					 | 
				
			||||||
						loc66.Add(table.Replace("'", "''"));
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (loc6.Count == 0) return loc1;
 | 
					 | 
				
			||||||
			var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
 | 
					 | 
				
			||||||
			var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sql = string.Format(@"
 | 
					 | 
				
			||||||
select
 | 
					 | 
				
			||||||
concat(a.table_schema, '.', a.table_name),
 | 
					 | 
				
			||||||
a.column_name,
 | 
					 | 
				
			||||||
a.data_type,
 | 
					 | 
				
			||||||
ifnull(a.character_maximum_length, 0) 'len',
 | 
					 | 
				
			||||||
a.column_type,
 | 
					 | 
				
			||||||
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
 | 
					 | 
				
			||||||
case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity',
 | 
					 | 
				
			||||||
a.column_comment 'comment'
 | 
					 | 
				
			||||||
from information_schema.columns a
 | 
					 | 
				
			||||||
where a.table_schema in ({1}) and a.table_name in ({0})
 | 
					 | 
				
			||||||
", loc8, databaseIn);
 | 
					 | 
				
			||||||
			ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				string table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				string column = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				string type = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				//long max_length = long.Parse(string.Concat(row[3]));
 | 
					 | 
				
			||||||
				string sqlType = string.Concat(row[4]);
 | 
					 | 
				
			||||||
				var m_len = Regex.Match(sqlType, @"\w+\((\d+)");
 | 
					 | 
				
			||||||
				int max_length = m_len.Success ? int.Parse(m_len.Groups[1].Value) : -1;
 | 
					 | 
				
			||||||
				bool is_nullable = string.Concat(row[5]) == "1";
 | 
					 | 
				
			||||||
				bool is_identity = string.Concat(row[6]) == "1";
 | 
					 | 
				
			||||||
				string comment = string.Concat(row[7]);
 | 
					 | 
				
			||||||
				if (max_length == 0) max_length = -1;
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc3[table_id].Add(column, new DbColumnInfo {
 | 
					 | 
				
			||||||
					Name = column,
 | 
					 | 
				
			||||||
					MaxLength = max_length,
 | 
					 | 
				
			||||||
					IsIdentity = is_identity,
 | 
					 | 
				
			||||||
					IsNullable = is_nullable,
 | 
					 | 
				
			||||||
					IsPrimary = false,
 | 
					 | 
				
			||||||
					DbTypeText = type,
 | 
					 | 
				
			||||||
					DbTypeTextFull = sqlType,
 | 
					 | 
				
			||||||
					Table = loc2[table_id],
 | 
					 | 
				
			||||||
					Coment = comment
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
				loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]);
 | 
					 | 
				
			||||||
				loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sql = string.Format(@"
 | 
					 | 
				
			||||||
select 
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
 | 
					 | 
				
			||||||
a.column_name,
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '/', a.table_name, '/', a.constraint_name) 'index_id',
 | 
					 | 
				
			||||||
1 'IsUnique',
 | 
					 | 
				
			||||||
case when constraint_name = 'PRIMARY' then 1 else 0 end 'IsPrimaryKey',
 | 
					 | 
				
			||||||
0 'IsClustered',
 | 
					 | 
				
			||||||
0 'IsDesc'
 | 
					 | 
				
			||||||
from information_schema.key_column_usage a
 | 
					 | 
				
			||||||
where a.constraint_schema in ({1}) and a.table_name in ({0}) and isnull(position_in_unique_constraint)
 | 
					 | 
				
			||||||
", loc8, databaseIn);
 | 
					 | 
				
			||||||
			ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
 | 
					 | 
				
			||||||
			var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				string table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				string column = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				string index_id = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				bool is_unique = string.Concat(row[3]) == "1";
 | 
					 | 
				
			||||||
				bool is_primary_key = string.Concat(row[4]) == "1";
 | 
					 | 
				
			||||||
				bool is_clustered = string.Concat(row[5]) == "1";
 | 
					 | 
				
			||||||
				int is_desc = int.Parse(string.Concat(row[6]));
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
 | 
					 | 
				
			||||||
				var loc9 = loc3[table_id][column];
 | 
					 | 
				
			||||||
				if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Dictionary<string, List<DbColumnInfo>> loc10 = null;
 | 
					 | 
				
			||||||
				List<DbColumnInfo> loc11 = null;
 | 
					 | 
				
			||||||
				if (!indexColumns.TryGetValue(table_id, out loc10))
 | 
					 | 
				
			||||||
					indexColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
 | 
					 | 
				
			||||||
				if (!loc10.TryGetValue(index_id, out loc11))
 | 
					 | 
				
			||||||
					loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
 | 
					 | 
				
			||||||
				loc11.Add(loc9);
 | 
					 | 
				
			||||||
				if (is_unique) {
 | 
					 | 
				
			||||||
					if (!uniqueColumns.TryGetValue(table_id, out loc10))
 | 
					 | 
				
			||||||
						uniqueColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
 | 
					 | 
				
			||||||
					if (!loc10.TryGetValue(index_id, out loc11))
 | 
					 | 
				
			||||||
						loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
 | 
					 | 
				
			||||||
					loc11.Add(loc9);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (string table_id in indexColumns.Keys) {
 | 
					 | 
				
			||||||
				foreach (var columns in indexColumns[table_id].Values)
 | 
					 | 
				
			||||||
					loc2[table_id].Indexes.Add(columns);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (string table_id in uniqueColumns.Keys) {
 | 
					 | 
				
			||||||
				foreach (var columns in uniqueColumns[table_id].Values) {
 | 
					 | 
				
			||||||
					columns.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
 | 
					 | 
				
			||||||
					loc2[table_id].Uniques.Add(columns);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sql = string.Format(@"
 | 
					 | 
				
			||||||
select 
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
 | 
					 | 
				
			||||||
a.column_name,
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '/', a.constraint_name) 'FKId',
 | 
					 | 
				
			||||||
concat(a.referenced_table_schema, '.', a.referenced_table_name) 'ref_table_id',
 | 
					 | 
				
			||||||
1 'IsForeignKey',
 | 
					 | 
				
			||||||
a.referenced_column_name 'ref_column'
 | 
					 | 
				
			||||||
from information_schema.key_column_usage a
 | 
					 | 
				
			||||||
where a.constraint_schema in ({1}) and a.table_name in ({0}) and not isnull(position_in_unique_constraint)
 | 
					 | 
				
			||||||
", loc8, databaseIn);
 | 
					 | 
				
			||||||
			ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				string table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				string column = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				string fk_id = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				string ref_table_id = string.Concat(row[3]);
 | 
					 | 
				
			||||||
				bool is_foreign_key = string.Concat(row[4]) == "1";
 | 
					 | 
				
			||||||
				string referenced_column = string.Concat(row[5]);
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
					ref_table_id = ref_table_id.Substring(ref_table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
 | 
					 | 
				
			||||||
				var loc9 = loc3[table_id][column];
 | 
					 | 
				
			||||||
				if (loc2.ContainsKey(ref_table_id) == false) continue;
 | 
					 | 
				
			||||||
				var loc10 = loc2[ref_table_id];
 | 
					 | 
				
			||||||
				var loc11 = loc3[ref_table_id][referenced_column];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Dictionary<string, DbForeignInfo> loc12 = null;
 | 
					 | 
				
			||||||
				DbForeignInfo loc13 = null;
 | 
					 | 
				
			||||||
				if (!fkColumns.TryGetValue(table_id, out loc12))
 | 
					 | 
				
			||||||
					fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
 | 
					 | 
				
			||||||
				if (!loc12.TryGetValue(fk_id, out loc13))
 | 
					 | 
				
			||||||
					loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc10 });
 | 
					 | 
				
			||||||
				loc13.Columns.Add(loc9);
 | 
					 | 
				
			||||||
				loc13.ReferencedColumns.Add(loc11);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (var table_id in fkColumns.Keys)
 | 
					 | 
				
			||||||
				foreach (var fk in fkColumns[table_id].Values)
 | 
					 | 
				
			||||||
					loc2[table_id].Foreigns.Add(fk);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			foreach (var table_id in loc3.Keys) {
 | 
					 | 
				
			||||||
				foreach (var loc5 in loc3[table_id].Values) {
 | 
					 | 
				
			||||||
					loc2[table_id].Columns.Add(loc5);
 | 
					 | 
				
			||||||
					if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
 | 
					 | 
				
			||||||
					if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (var loc4 in loc2.Values) {
 | 
					 | 
				
			||||||
				if (loc4.Primarys.Count == 0 && loc4.Uniques.Count > 0) {
 | 
					 | 
				
			||||||
					foreach (var loc5 in loc4.Uniques[0]) {
 | 
					 | 
				
			||||||
						loc5.IsPrimary = true;
 | 
					 | 
				
			||||||
						loc4.Primarys.Add(loc5);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
 | 
					 | 
				
			||||||
				loc4.Columns.Sort((c1, c2) => {
 | 
					 | 
				
			||||||
					int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
 | 
					 | 
				
			||||||
					if (compare == 0) {
 | 
					 | 
				
			||||||
						bool b1 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c1.Name) != null) != null;
 | 
					 | 
				
			||||||
						bool b2 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c2.Name) != null) != null;
 | 
					 | 
				
			||||||
						compare = b2.CompareTo(b1);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
 | 
					 | 
				
			||||||
					return compare;
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
				loc1.Add(loc4);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			loc1.Sort((t1, t2) => {
 | 
					 | 
				
			||||||
				var ret = t1.Schema.CompareTo(t2.Schema);
 | 
					 | 
				
			||||||
				if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
 | 
					 | 
				
			||||||
				return ret;
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			foreach(var loc4 in loc1) {
 | 
					 | 
				
			||||||
				var dicUniques = new Dictionary<string, List<DbColumnInfo>>();
 | 
					 | 
				
			||||||
				if (loc4.Primarys.Count > 0) dicUniques.Add(string.Join(",", loc4.Primarys.Select(a => a.Name)), loc4.Primarys);
 | 
					 | 
				
			||||||
				foreach(var loc5 in loc4.Uniques) {
 | 
					 | 
				
			||||||
					var dickey = string.Join(",", loc5.Select(a => a.Name));
 | 
					 | 
				
			||||||
					if (dicUniques.ContainsKey(dickey)) continue;
 | 
					 | 
				
			||||||
					dicUniques.Add(dickey, loc5);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc4.Uniques = dicUniques.Values.ToList();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			loc2.Clear();
 | 
					 | 
				
			||||||
			loc3.Clear();
 | 
					 | 
				
			||||||
			return loc1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
 | 
					 | 
				
			||||||
			return new List<DbEnumInfo>();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -25,7 +25,7 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
		public IAdo Ado { get; }
 | 
							public IAdo Ado { get; }
 | 
				
			||||||
		public ICache Cache { get; }
 | 
							public ICache Cache { get; }
 | 
				
			||||||
		public ICodeFirst CodeFirst { get; }
 | 
							public ICodeFirst CodeFirst { get; }
 | 
				
			||||||
		public IDbFirst DbFirst { get; }
 | 
							public IDbFirst DbFirst { get { throw new NotImplementedException(); } }
 | 
				
			||||||
		public OracleProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
 | 
							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");
 | 
								if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.Oracle");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,7 +35,6 @@ namespace FreeSql.Oracle {
 | 
				
			|||||||
			this.Cache = new CacheProvider(cache, log);
 | 
								this.Cache = new CacheProvider(cache, log);
 | 
				
			||||||
			this.Ado = new OracleAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
 | 
								this.Ado = new OracleAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.DbFirst = new OracleDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
 | 
					 | 
				
			||||||
			this.InternalCommonUtils.CodeFirst = this.CodeFirst = new OracleCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
 | 
								this.InternalCommonUtils.CodeFirst = this.CodeFirst = new OracleCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -270,6 +270,7 @@ and b.nspname || '.' || a.relname not in ('public.geography_columns','public.geo
 | 
				
			|||||||
				sql = $@"
 | 
									sql = $@"
 | 
				
			||||||
select
 | 
					select
 | 
				
			||||||
ns.nspname || '.' || c.relname as id, 
 | 
					ns.nspname || '.' || c.relname as id, 
 | 
				
			||||||
 | 
					a.attname,
 | 
				
			||||||
t.typname,
 | 
					t.typname,
 | 
				
			||||||
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
 | 
					case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
 | 
				
			||||||
case when t.typelem = 0 then t.typname else t2.typname end,
 | 
					case when t.typelem = 0 then t.typname else t2.typname end,
 | 
				
			||||||
@@ -289,7 +290,7 @@ left join pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
 | 
				
			|||||||
left join pg_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
 | 
					left join pg_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
 | 
				
			||||||
inner join pg_namespace ns on ns.oid = c.relnamespace
 | 
					inner join pg_namespace ns on ns.oid = c.relnamespace
 | 
				
			||||||
inner join pg_namespace ns2 on ns2.oid = t.typnamespace
 | 
					inner join pg_namespace ns2 on ns2.oid = t.typnamespace
 | 
				
			||||||
where ns.nspname || '.' || c.relname in ({loc88})";
 | 
					where ns.nspname || '.' || c.relname in ({loc8})";
 | 
				
			||||||
				ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
									ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
				
			||||||
				if (ds == null) return loc1;
 | 
									if (ds == null) return loc1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,385 +0,0 @@
 | 
				
			|||||||
using FreeSql.DatabaseModel;
 | 
					 | 
				
			||||||
using FreeSql.Internal;
 | 
					 | 
				
			||||||
using MySql.Data.MySqlClient;
 | 
					 | 
				
			||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Data;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Text.RegularExpressions;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace FreeSql.Sqlite {
 | 
					 | 
				
			||||||
	class SqliteDbFirst : IDbFirst {
 | 
					 | 
				
			||||||
		IFreeSql _orm;
 | 
					 | 
				
			||||||
		protected CommonUtils _commonUtils;
 | 
					 | 
				
			||||||
		protected CommonExpression _commonExpression;
 | 
					 | 
				
			||||||
		public SqliteDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
 | 
					 | 
				
			||||||
			_orm = orm;
 | 
					 | 
				
			||||||
			_commonUtils = commonUtils;
 | 
					 | 
				
			||||||
			_commonExpression = commonExpression;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public int GetDbType(DbColumnInfo column) => (int)GetMySqlDbType(column);
 | 
					 | 
				
			||||||
		MySqlDbType GetMySqlDbType(DbColumnInfo column) {
 | 
					 | 
				
			||||||
			var is_unsigned = column.DbTypeTextFull.ToLower().EndsWith(" unsigned");
 | 
					 | 
				
			||||||
			switch (column.DbTypeText.ToLower()) {
 | 
					 | 
				
			||||||
				case "bit": return MySqlDbType.Bit;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "tinyint": return is_unsigned ? MySqlDbType.UByte : MySqlDbType.Byte;
 | 
					 | 
				
			||||||
				case "smallint": return is_unsigned ? MySqlDbType.UInt16 : MySqlDbType.Int16;
 | 
					 | 
				
			||||||
				case "mediumint": return is_unsigned ? MySqlDbType.UInt24 : MySqlDbType.Int24;
 | 
					 | 
				
			||||||
				case "int": return is_unsigned ? MySqlDbType.UInt32 : MySqlDbType.Int32;
 | 
					 | 
				
			||||||
				case "bigint": return is_unsigned ? MySqlDbType.UInt64 : MySqlDbType.Int64;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "real":
 | 
					 | 
				
			||||||
				case "double": return MySqlDbType.Double;
 | 
					 | 
				
			||||||
				case "float": return MySqlDbType.Float;
 | 
					 | 
				
			||||||
				case "numeric":
 | 
					 | 
				
			||||||
				case "decimal": return MySqlDbType.Decimal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "year": return MySqlDbType.Year;
 | 
					 | 
				
			||||||
				case "time": return MySqlDbType.Time;
 | 
					 | 
				
			||||||
				case "date": return MySqlDbType.Date;
 | 
					 | 
				
			||||||
				case "timestamp": return MySqlDbType.Timestamp;
 | 
					 | 
				
			||||||
				case "datetime": return MySqlDbType.DateTime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "tinyblob": return MySqlDbType.TinyBlob;
 | 
					 | 
				
			||||||
				case "blob": return MySqlDbType.Blob;
 | 
					 | 
				
			||||||
				case "mediumblob": return MySqlDbType.MediumBlob;
 | 
					 | 
				
			||||||
				case "longblob": return MySqlDbType.LongBlob;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "binary": return MySqlDbType.Binary;
 | 
					 | 
				
			||||||
				case "varbinary": return MySqlDbType.VarBinary;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "tinytext": return MySqlDbType.TinyText;
 | 
					 | 
				
			||||||
				case "text": return MySqlDbType.Text;
 | 
					 | 
				
			||||||
				case "mediumtext": return MySqlDbType.MediumText;
 | 
					 | 
				
			||||||
				case "longtext": return MySqlDbType.LongText;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "char": return column.MaxLength == 36 ? MySqlDbType.Guid : MySqlDbType.String;
 | 
					 | 
				
			||||||
				case "varchar": return MySqlDbType.VarChar;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "set": return MySqlDbType.Set;
 | 
					 | 
				
			||||||
				case "enum": return MySqlDbType.Enum;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case "point": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "linestring": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "polygon": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "geometry": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "multipoint": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "multilinestring": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "multipolygon": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				case "geometrycollection": return MySqlDbType.Geometry;
 | 
					 | 
				
			||||||
				default: return MySqlDbType.String;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Bit, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Byte, ("(sbyte?)", "sbyte.Parse({0})", "{0}.ToString()", "sbyte?", typeof(sbyte), typeof(sbyte?), "{0}.Value", "GetByte") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int16, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int24, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int32, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Int64, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UByte, ("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt16, ("(ushort?)", "ushort.Parse({0})", "{0}.ToString()", "ushort?", typeof(ushort), typeof(ushort?), "{0}.Value", "GetInt16") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt24, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt32, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.UInt64, ("(ulong?)", "ulong.Parse({0})", "{0}.ToString()", "ulong?", typeof(ulong), typeof(ulong?), "{0}.Value", "GetInt64") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Double, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Float, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Decimal, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Year, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Time, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Timestamp, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.DateTime, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.TinyBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Blob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.MediumBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.LongBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Binary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.VarBinary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.TinyText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.MediumText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.LongText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Guid, ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid?", typeof(Guid), typeof(Guid?), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.String, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.VarString, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Set, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Set", typeof(Enum), typeof(Enum), "{0}", "GetInt64") },
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Enum, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Enum", typeof(Enum), typeof(Enum), "{0}", "GetInt64") },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				{ (int)MySqlDbType.Geometry, ("(MygisGeometry)", "MygisGeometry.Parse({0}.Replace(StringifySplit, \"|\"))", "{0}.AsText().Replace(\"|\", StringifySplit)", "MygisGeometry", typeof(MygisGeometry), typeof(MygisGeometry), "{0}", "GetString") },
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
 | 
					 | 
				
			||||||
		public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csParse : null;
 | 
					 | 
				
			||||||
		public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csStringify : null;
 | 
					 | 
				
			||||||
		public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null;
 | 
					 | 
				
			||||||
		public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeInfo : null;
 | 
					 | 
				
			||||||
		public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeValue : null;
 | 
					 | 
				
			||||||
		public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public List<string> GetDatabases() {
 | 
					 | 
				
			||||||
			var sql = @" select schema_name from information_schema.schemata where schema_name not in ('information_schema', 'mysql', 'performance_schema')";
 | 
					 | 
				
			||||||
			var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public List<DbTableInfo> GetTablesByDatabase(params string[] database) {
 | 
					 | 
				
			||||||
			var loc1 = new List<DbTableInfo>();
 | 
					 | 
				
			||||||
			var loc2 = new Dictionary<string, DbTableInfo>();
 | 
					 | 
				
			||||||
			var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (database == null || database.Any() == false) return loc1;
 | 
					 | 
				
			||||||
			var databaseIn = string.Join(",", database.Select(a => "{0}".FormatMySql(a)));
 | 
					 | 
				
			||||||
			var sql = string.Format(@"
 | 
					 | 
				
			||||||
select 
 | 
					 | 
				
			||||||
concat(a.table_schema, '.', a.table_name) 'id',
 | 
					 | 
				
			||||||
a.table_schema 'schema',
 | 
					 | 
				
			||||||
a.table_name 'table',
 | 
					 | 
				
			||||||
a.table_type 'type'
 | 
					 | 
				
			||||||
from information_schema.tables a
 | 
					 | 
				
			||||||
where a.table_schema in ({0})", databaseIn);
 | 
					 | 
				
			||||||
			var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var loc6 = new List<string>();
 | 
					 | 
				
			||||||
			var loc66 = new List<string>();
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				var table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				var schema = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				var table = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				var type = string.Concat(row[3]) == "VIEW" ? DbTableType.VIEW : DbTableType.TABLE;
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
					schema = "";
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc2.Add(table_id, new DbTableInfo { Id = table_id, Schema = schema, Name = table, Type = type });
 | 
					 | 
				
			||||||
				loc3.Add(table_id, new Dictionary<string, DbColumnInfo>());
 | 
					 | 
				
			||||||
				switch (type) {
 | 
					 | 
				
			||||||
					case DbTableType.TABLE:
 | 
					 | 
				
			||||||
					case DbTableType.VIEW:
 | 
					 | 
				
			||||||
						loc6.Add(table.Replace("'", "''"));
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					case DbTableType.StoreProcedure:
 | 
					 | 
				
			||||||
						loc66.Add(table.Replace("'", "''"));
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (loc6.Count == 0) return loc1;
 | 
					 | 
				
			||||||
			var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
 | 
					 | 
				
			||||||
			var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sql = string.Format(@"
 | 
					 | 
				
			||||||
select
 | 
					 | 
				
			||||||
concat(a.table_schema, '.', a.table_name),
 | 
					 | 
				
			||||||
a.column_name,
 | 
					 | 
				
			||||||
a.data_type,
 | 
					 | 
				
			||||||
ifnull(a.character_maximum_length, 0) 'len',
 | 
					 | 
				
			||||||
a.column_type,
 | 
					 | 
				
			||||||
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
 | 
					 | 
				
			||||||
case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity',
 | 
					 | 
				
			||||||
a.column_comment 'comment'
 | 
					 | 
				
			||||||
from information_schema.columns a
 | 
					 | 
				
			||||||
where a.table_schema in ({1}) and a.table_name in ({0})
 | 
					 | 
				
			||||||
", loc8, databaseIn);
 | 
					 | 
				
			||||||
			ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				string table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				string column = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				string type = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				//long max_length = long.Parse(string.Concat(row[3]));
 | 
					 | 
				
			||||||
				string sqlType = string.Concat(row[4]);
 | 
					 | 
				
			||||||
				var m_len = Regex.Match(sqlType, @"\w+\((\d+)");
 | 
					 | 
				
			||||||
				int max_length = m_len.Success ? int.Parse(m_len.Groups[1].Value) : -1;
 | 
					 | 
				
			||||||
				bool is_nullable = string.Concat(row[5]) == "1";
 | 
					 | 
				
			||||||
				bool is_identity = string.Concat(row[6]) == "1";
 | 
					 | 
				
			||||||
				string comment = string.Concat(row[7]);
 | 
					 | 
				
			||||||
				if (max_length == 0) max_length = -1;
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc3[table_id].Add(column, new DbColumnInfo {
 | 
					 | 
				
			||||||
					Name = column,
 | 
					 | 
				
			||||||
					MaxLength = max_length,
 | 
					 | 
				
			||||||
					IsIdentity = is_identity,
 | 
					 | 
				
			||||||
					IsNullable = is_nullable,
 | 
					 | 
				
			||||||
					IsPrimary = false,
 | 
					 | 
				
			||||||
					DbTypeText = type,
 | 
					 | 
				
			||||||
					DbTypeTextFull = sqlType,
 | 
					 | 
				
			||||||
					Table = loc2[table_id],
 | 
					 | 
				
			||||||
					Coment = comment
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
				loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]);
 | 
					 | 
				
			||||||
				loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sql = string.Format(@"
 | 
					 | 
				
			||||||
select 
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
 | 
					 | 
				
			||||||
a.column_name,
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '/', a.table_name, '/', a.constraint_name) 'index_id',
 | 
					 | 
				
			||||||
1 'IsUnique',
 | 
					 | 
				
			||||||
case when constraint_name = 'PRIMARY' then 1 else 0 end 'IsPrimaryKey',
 | 
					 | 
				
			||||||
0 'IsClustered',
 | 
					 | 
				
			||||||
0 'IsDesc'
 | 
					 | 
				
			||||||
from information_schema.key_column_usage a
 | 
					 | 
				
			||||||
where a.constraint_schema in ({1}) and a.table_name in ({0}) and isnull(position_in_unique_constraint)
 | 
					 | 
				
			||||||
", loc8, databaseIn);
 | 
					 | 
				
			||||||
			ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
 | 
					 | 
				
			||||||
			var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				string table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				string column = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				string index_id = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				bool is_unique = string.Concat(row[3]) == "1";
 | 
					 | 
				
			||||||
				bool is_primary_key = string.Concat(row[4]) == "1";
 | 
					 | 
				
			||||||
				bool is_clustered = string.Concat(row[5]) == "1";
 | 
					 | 
				
			||||||
				int is_desc = int.Parse(string.Concat(row[6]));
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
 | 
					 | 
				
			||||||
				var loc9 = loc3[table_id][column];
 | 
					 | 
				
			||||||
				if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Dictionary<string, List<DbColumnInfo>> loc10 = null;
 | 
					 | 
				
			||||||
				List<DbColumnInfo> loc11 = null;
 | 
					 | 
				
			||||||
				if (!indexColumns.TryGetValue(table_id, out loc10))
 | 
					 | 
				
			||||||
					indexColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
 | 
					 | 
				
			||||||
				if (!loc10.TryGetValue(index_id, out loc11))
 | 
					 | 
				
			||||||
					loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
 | 
					 | 
				
			||||||
				loc11.Add(loc9);
 | 
					 | 
				
			||||||
				if (is_unique) {
 | 
					 | 
				
			||||||
					if (!uniqueColumns.TryGetValue(table_id, out loc10))
 | 
					 | 
				
			||||||
						uniqueColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
 | 
					 | 
				
			||||||
					if (!loc10.TryGetValue(index_id, out loc11))
 | 
					 | 
				
			||||||
						loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
 | 
					 | 
				
			||||||
					loc11.Add(loc9);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (string table_id in indexColumns.Keys) {
 | 
					 | 
				
			||||||
				foreach (var columns in indexColumns[table_id].Values)
 | 
					 | 
				
			||||||
					loc2[table_id].Indexes.Add(columns);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (string table_id in uniqueColumns.Keys) {
 | 
					 | 
				
			||||||
				foreach (var columns in uniqueColumns[table_id].Values) {
 | 
					 | 
				
			||||||
					columns.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
 | 
					 | 
				
			||||||
					loc2[table_id].Uniques.Add(columns);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sql = string.Format(@"
 | 
					 | 
				
			||||||
select 
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
 | 
					 | 
				
			||||||
a.column_name,
 | 
					 | 
				
			||||||
concat(a.constraint_schema, '/', a.constraint_name) 'FKId',
 | 
					 | 
				
			||||||
concat(a.referenced_table_schema, '.', a.referenced_table_name) 'ref_table_id',
 | 
					 | 
				
			||||||
1 'IsForeignKey',
 | 
					 | 
				
			||||||
a.referenced_column_name 'ref_column'
 | 
					 | 
				
			||||||
from information_schema.key_column_usage a
 | 
					 | 
				
			||||||
where a.constraint_schema in ({1}) and a.table_name in ({0}) and not isnull(position_in_unique_constraint)
 | 
					 | 
				
			||||||
", loc8, databaseIn);
 | 
					 | 
				
			||||||
			ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
 | 
					 | 
				
			||||||
			if (ds == null) return loc1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
 | 
					 | 
				
			||||||
			foreach (var row in ds) {
 | 
					 | 
				
			||||||
				string table_id = string.Concat(row[0]);
 | 
					 | 
				
			||||||
				string column = string.Concat(row[1]);
 | 
					 | 
				
			||||||
				string fk_id = string.Concat(row[2]);
 | 
					 | 
				
			||||||
				string ref_table_id = string.Concat(row[3]);
 | 
					 | 
				
			||||||
				bool is_foreign_key = string.Concat(row[4]) == "1";
 | 
					 | 
				
			||||||
				string referenced_column = string.Concat(row[5]);
 | 
					 | 
				
			||||||
				if (database.Length == 1) {
 | 
					 | 
				
			||||||
					table_id = table_id.Substring(table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
					ref_table_id = ref_table_id.Substring(ref_table_id.IndexOf('.') + 1);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
 | 
					 | 
				
			||||||
				var loc9 = loc3[table_id][column];
 | 
					 | 
				
			||||||
				if (loc2.ContainsKey(ref_table_id) == false) continue;
 | 
					 | 
				
			||||||
				var loc10 = loc2[ref_table_id];
 | 
					 | 
				
			||||||
				var loc11 = loc3[ref_table_id][referenced_column];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				Dictionary<string, DbForeignInfo> loc12 = null;
 | 
					 | 
				
			||||||
				DbForeignInfo loc13 = null;
 | 
					 | 
				
			||||||
				if (!fkColumns.TryGetValue(table_id, out loc12))
 | 
					 | 
				
			||||||
					fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
 | 
					 | 
				
			||||||
				if (!loc12.TryGetValue(fk_id, out loc13))
 | 
					 | 
				
			||||||
					loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc10 });
 | 
					 | 
				
			||||||
				loc13.Columns.Add(loc9);
 | 
					 | 
				
			||||||
				loc13.ReferencedColumns.Add(loc11);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (var table_id in fkColumns.Keys)
 | 
					 | 
				
			||||||
				foreach (var fk in fkColumns[table_id].Values)
 | 
					 | 
				
			||||||
					loc2[table_id].Foreigns.Add(fk);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			foreach (var table_id in loc3.Keys) {
 | 
					 | 
				
			||||||
				foreach (var loc5 in loc3[table_id].Values) {
 | 
					 | 
				
			||||||
					loc2[table_id].Columns.Add(loc5);
 | 
					 | 
				
			||||||
					if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
 | 
					 | 
				
			||||||
					if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			foreach (var loc4 in loc2.Values) {
 | 
					 | 
				
			||||||
				if (loc4.Primarys.Count == 0 && loc4.Uniques.Count > 0) {
 | 
					 | 
				
			||||||
					foreach (var loc5 in loc4.Uniques[0]) {
 | 
					 | 
				
			||||||
						loc5.IsPrimary = true;
 | 
					 | 
				
			||||||
						loc4.Primarys.Add(loc5);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
 | 
					 | 
				
			||||||
				loc4.Columns.Sort((c1, c2) => {
 | 
					 | 
				
			||||||
					int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
 | 
					 | 
				
			||||||
					if (compare == 0) {
 | 
					 | 
				
			||||||
						bool b1 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c1.Name) != null) != null;
 | 
					 | 
				
			||||||
						bool b2 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c2.Name) != null) != null;
 | 
					 | 
				
			||||||
						compare = b2.CompareTo(b1);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
 | 
					 | 
				
			||||||
					return compare;
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
				loc1.Add(loc4);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			loc1.Sort((t1, t2) => {
 | 
					 | 
				
			||||||
				var ret = t1.Schema.CompareTo(t2.Schema);
 | 
					 | 
				
			||||||
				if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
 | 
					 | 
				
			||||||
				return ret;
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			foreach(var loc4 in loc1) {
 | 
					 | 
				
			||||||
				var dicUniques = new Dictionary<string, List<DbColumnInfo>>();
 | 
					 | 
				
			||||||
				if (loc4.Primarys.Count > 0) dicUniques.Add(string.Join(",", loc4.Primarys.Select(a => a.Name)), loc4.Primarys);
 | 
					 | 
				
			||||||
				foreach(var loc5 in loc4.Uniques) {
 | 
					 | 
				
			||||||
					var dickey = string.Join(",", loc5.Select(a => a.Name));
 | 
					 | 
				
			||||||
					if (dicUniques.ContainsKey(dickey)) continue;
 | 
					 | 
				
			||||||
					dicUniques.Add(dickey, loc5);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				loc4.Uniques = dicUniques.Values.ToList();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			loc2.Clear();
 | 
					 | 
				
			||||||
			loc3.Clear();
 | 
					 | 
				
			||||||
			return loc1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
 | 
					 | 
				
			||||||
			return new List<DbEnumInfo>();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -25,7 +25,7 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
		public IAdo Ado { get; }
 | 
							public IAdo Ado { get; }
 | 
				
			||||||
		public ICache Cache { get; }
 | 
							public ICache Cache { get; }
 | 
				
			||||||
		public ICodeFirst CodeFirst { get; }
 | 
							public ICodeFirst CodeFirst { get; }
 | 
				
			||||||
		public IDbFirst DbFirst { get; }
 | 
							public IDbFirst DbFirst { get { throw new NotImplementedException(); } }
 | 
				
			||||||
		public SqliteProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
 | 
							public SqliteProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
 | 
				
			||||||
			if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.Sqlite");
 | 
								if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.Sqlite");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,7 +35,6 @@ namespace FreeSql.Sqlite {
 | 
				
			|||||||
			this.Cache = new CacheProvider(cache, log);
 | 
								this.Cache = new CacheProvider(cache, log);
 | 
				
			||||||
			this.Ado = new SqliteAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
 | 
								this.Ado = new SqliteAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.DbFirst = new SqliteDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
 | 
					 | 
				
			||||||
			this.InternalCommonUtils.CodeFirst = this.CodeFirst = new SqliteCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
 | 
								this.InternalCommonUtils.CodeFirst = this.CodeFirst = new SqliteCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					public static class Const {
 | 
				
			||||||
 | 
						public static IFreeSql sqlserver = new FreeSql.FreeSqlBuilder()
 | 
				
			||||||
 | 
							.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10")
 | 
				
			||||||
 | 
							.Build();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,240 @@
 | 
				
			|||||||
 | 
					{%if (table.Type == DbTableType.StoreProcedure) {
 | 
				
			||||||
 | 
						print("return;");
 | 
				
			||||||
 | 
						return rTn;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 %}using System;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.ComponentModel;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using FreeSql;
 | 
				
			||||||
 | 
					using FreeSql.DataAnnotations;
 | 
				
			||||||
 | 
					{%
 | 
				
			||||||
 | 
					var dbf = dbfirst as FreeSql.IDbFirst;
 | 
				
			||||||
 | 
					var cols = (table.Columns as List<DbColumnInfo>);
 | 
				
			||||||
 | 
					var pks = (table.Primarys as List<DbColumnInfo>);
 | 
				
			||||||
 | 
					var fks = (table.Foreigns as List<DbForeignInfo>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Func<string, string> UString = stra => stra.Substring(0, 1).ToUpper() + stra.Substring(1);
 | 
				
			||||||
 | 
					Func<DbColumnInfo, string> GetCsType = cola3 => {
 | 
				
			||||||
 | 
						return dbf.GetCsType(cola3);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					Func<DbForeignInfo, string> GetFkObjectName = fkx => {
 | 
				
			||||||
 | 
						var eqfks = fks.Where(fk22a => fk22a.ReferencedTable.Name == fkx.ReferencedTable.Name);
 | 
				
			||||||
 | 
						if (eqfks.Count() == 1) return "Obj_" + fkx.ReferencedTable.Name;
 | 
				
			||||||
 | 
						var fkretname = fkx.Columns[0].Name;
 | 
				
			||||||
 | 
						if (fkretname.EndsWith(fkx.ReferencedColumns[0].Name, StringComparison.CurrentCultureIgnoreCase)) fkretname = fkretname.Substring(0, fkretname.Length - fkx.ReferencedColumns[0].Name.Length).TrimEnd('_');
 | 
				
			||||||
 | 
						if (fkretname.EndsWith(fkx.ReferencedTable.Name, StringComparison.CurrentCultureIgnoreCase)) fkretname = fkretname.Substring(0, fkretname.Length - fkx.ReferencedTable.Name.Length).TrimEnd('_');
 | 
				
			||||||
 | 
						if (fkretname.StartsWith(fkx.ReferencedTable.Name, StringComparison.CurrentCultureIgnoreCase)) fkretname = fkretname.Substring(fkx.ReferencedTable.Name.Length).TrimStart('_');
 | 
				
			||||||
 | 
						return "Obj_" + fkx.ReferencedTable.Name + (string.IsNullOrEmpty(fkretname) ? "" : ("_" + fkretname));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					namespace test.Model {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[JsonObject(MemberSerialization.OptIn), Table(Name = "{#!string.IsNullOrEmpty(table.Schema) ? table.Schema + "." : ""}{#table.Name}"{if cols.Where(cola003 => cola003.Name.ToLower() == "is_deleted" || cola003.Name.ToLower() == "isdeleted").Any()}, SelectFilter = "a.IsDeleted = 1"{/if})]
 | 
				
			||||||
 | 
						public partial class {#UString(table.Name)} {{for col,index in table.Columns}{%
 | 
				
			||||||
 | 
								var findfks = fks.Where(fkaa => fkaa.Columns.Where(fkaac1 => fkaac1.Name == col.Name).Any());
 | 
				
			||||||
 | 
							%}{if findfks.Any() == false}
 | 
				
			||||||
 | 
							{if string.IsNullOrEmpty(col.Coment) == false}/// <summary>
 | 
				
			||||||
 | 
							/// {#col.Coment.Replace("\r\n", "\n").Replace("\n", "\r\n		/// ")}
 | 
				
			||||||
 | 
							/// </summary>{/if}
 | 
				
			||||||
 | 
							[JsonProperty, Column(Name = "{#col.Name}", DbType = "{#col.DbTypeTextFull}"{if col.IsPrimary == true}, IsPrimary = true{/if}{if col.IsIdentity == true}, IsIdentity = true{/if}{if col.IsNullable == true}, IsNullable = true{/if})]
 | 
				
			||||||
 | 
							public {#GetCsType(col)} {#UString(col.Name)} { get; set; }
 | 
				
			||||||
 | 
							{else}
 | 
				
			||||||
 | 
							private {#GetCsType(col)} _{#UString(col.Name)};
 | 
				
			||||||
 | 
							{if string.IsNullOrEmpty(col.Coment) == false}/// <summary>
 | 
				
			||||||
 | 
							/// {#col.Coment.Replace("\r\n", "\n").Replace("\n", "\r\n		/// ")}
 | 
				
			||||||
 | 
							/// </summary>{/if}
 | 
				
			||||||
 | 
							[JsonProperty, Column(Name = "{#col.Name}", DbType = "{#col.DbTypeTextFull}"{if col.IsPrimary == true}, IsPrimary = true{/if}{if col.IsIdentity == true}, IsIdentity = true{/if}{if col.IsNullable == true}, IsNullable = true{/if})]
 | 
				
			||||||
 | 
							public {#GetCsType(col)} {#UString(col.Name)} { get => _{#UString(col.Name)}; set {
 | 
				
			||||||
 | 
								if (_{#UString(col.Name)} == value) return;
 | 
				
			||||||
 | 
								_{#UString(col.Name)} = value;{for fkcok2 in findfks}
 | 
				
			||||||
 | 
								{#GetFkObjectName(fkcok2)} = null;{/for}
 | 
				
			||||||
 | 
							} }
 | 
				
			||||||
 | 
							{/if}{/for}{for fk in fks}
 | 
				
			||||||
 | 
							public {#UString(fk.ReferencedTable.Name)} {#GetFkObjectName(fk)} { get; set; }
 | 
				
			||||||
 | 
							{/for}
 | 
				
			||||||
 | 
							internal static IFreeSql freesql => Const.sqlserver;
 | 
				
			||||||
 | 
							public static ISelect<{#UString(table.Name)}> Select => freesql.Select<{#UString(table.Name)}>();
 | 
				
			||||||
 | 
					{if (table.Uniques.Count > 0)}
 | 
				
			||||||
 | 
							public static int ItemCacheTimeout = 180;{for uk001 in table.Uniques}{%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							string parms = string.Empty;
 | 
				
			||||||
 | 
							string parmsByWhereLambda = string.Empty;
 | 
				
			||||||
 | 
							string parmsBy = "By";
 | 
				
			||||||
 | 
							string parmsNodeTypeUpdateCacheRemove = string.Empty;
 | 
				
			||||||
 | 
							foreach (var uk001col in uk001) {
 | 
				
			||||||
 | 
								string getcstype = GetCsType(uk001col);
 | 
				
			||||||
 | 
								parms += getcstype.Replace("?", "") + " " + UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
								parmsByWhereLambda += "a." + UString(uk001col.Name) + " == " + UString(uk001col.Name) + " && ";
 | 
				
			||||||
 | 
								parmsBy += UString(uk001col.Name) + "And";
 | 
				
			||||||
 | 
								parmsNodeTypeUpdateCacheRemove += "item." + UString(uk001col.Name) + ", \"_,_\", ";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							parms = parms.Substring(0, parms.Length - 2);
 | 
				
			||||||
 | 
							parmsByWhereLambda = parmsByWhereLambda.Substring(0, parmsByWhereLambda.Length - 4);
 | 
				
			||||||
 | 
							parmsBy = parmsBy.Substring(0, parmsBy.Length - 3);
 | 
				
			||||||
 | 
							parmsNodeTypeUpdateCacheRemove = parmsNodeTypeUpdateCacheRemove.Substring(0, parmsNodeTypeUpdateCacheRemove.Length - 9);
 | 
				
			||||||
 | 
							%}
 | 
				
			||||||
 | 
							public static {#UString(table.Name)} GetItem{#uk001[0].IsPrimary ? string.Empty : parmsBy}({#parms}) => Select.Where(a => {#parmsByWhereLambda}).Caching(ItemCacheTimeout, string.Concat("test:{#table.Name}{#uk001[0].IsPrimary ? string.Empty : parmsBy}:", {#parmsNodeTypeUpdateCacheRemove.Replace("item.", "")})).ToOne();{/for}
 | 
				
			||||||
 | 
					{for uk001 in table.Uniques}{%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							string parms = string.Empty;
 | 
				
			||||||
 | 
							string parmsByWhereLambda = string.Empty;
 | 
				
			||||||
 | 
							string parmsNewItem = string.Empty;
 | 
				
			||||||
 | 
							string parmsBy = "By";
 | 
				
			||||||
 | 
							string parmsNoneType = string.Empty;
 | 
				
			||||||
 | 
							foreach (var uk001col in uk001) {
 | 
				
			||||||
 | 
								string getcstype = GetCsType(uk001col);
 | 
				
			||||||
 | 
								parms += getcstype.Replace("?", "") + " " + UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
								parmsByWhereLambda += "a." + UString(uk001col.Name) + " == " + UString(uk001col.Name) + " && ";
 | 
				
			||||||
 | 
								parmsNewItem += UString(uk001col.Name) + " = " + UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
								parmsBy += UString(uk001col.Name) + "And";
 | 
				
			||||||
 | 
								parmsNoneType += UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							parms = parms.Substring(0, parms.Length - 2);
 | 
				
			||||||
 | 
							parmsByWhereLambda = parmsByWhereLambda.Substring(0, parmsByWhereLambda.Length - 4);
 | 
				
			||||||
 | 
							parmsNewItem = parmsNewItem.Substring(0, parmsNewItem.Length - 2);
 | 
				
			||||||
 | 
							parmsBy = parmsBy.Substring(0, parmsBy.Length - 3);
 | 
				
			||||||
 | 
							parmsNoneType = parmsNoneType.Substring(0, parmsNoneType.Length - 2);
 | 
				
			||||||
 | 
							%}
 | 
				
			||||||
 | 
							public static long Delete{#uk001[0].IsPrimary ? string.Empty : parmsBy}({#parms}) {
 | 
				
			||||||
 | 
								var affrows = freesql.Delete<{#UString(table.Name)}>().Where(a => {#parmsByWhereLambda}).ExecuteAffrows();{if table.Uniques.Count > 1}
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(GetItem{#uk001[0].IsPrimary ? string.Empty : parmsBy}({#parmsNoneType}));{else}
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(new {#UString(table.Name)} { {#parmsNewItem} });{/if}
 | 
				
			||||||
 | 
								return affrows;
 | 
				
			||||||
 | 
							}{/for}
 | 
				
			||||||
 | 
					{for fkcoldel in fks}{%
 | 
				
			||||||
 | 
							string parms = string.Empty;
 | 
				
			||||||
 | 
							string parmsBy = "By";
 | 
				
			||||||
 | 
							string parmsByWhereLambda = string.Empty;
 | 
				
			||||||
 | 
							foreach( var fkcoldelcol in fkcoldel.Columns) {
 | 
				
			||||||
 | 
								string getcstype = GetCsType(fkcoldelcol);
 | 
				
			||||||
 | 
								parms += getcstype.Replace("?", "") + " " + UString(fkcoldelcol.Name) + ", ";
 | 
				
			||||||
 | 
								parmsBy += UString(fkcoldelcol.Name) + "And";
 | 
				
			||||||
 | 
								parmsByWhereLambda += "a." + UString(fkcoldelcol.Name) + " == " + UString(fkcoldelcol.Name) + " && ";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							parms = parms.Substring(0, parms.Length - 2);
 | 
				
			||||||
 | 
							parmsBy = parmsBy.Substring(0, parmsBy.Length - 3);
 | 
				
			||||||
 | 
							parmsByWhereLambda = parmsByWhereLambda.Substring(0, parmsByWhereLambda.Length - 4);
 | 
				
			||||||
 | 
							%}
 | 
				
			||||||
 | 
							public static long DeleteBy{#parmsBy}({#parms}) {
 | 
				
			||||||
 | 
								return freesql.Delete<{#UString(table.Name)}>().Where(a => {#parmsByWhereLambda}).ExecuteAffrows(); //删除缓存
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					{/for}{% string redisRemoveCode = string.Empty; %}{for uk001 in table.Uniques}{%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							string parmsBy = "By";
 | 
				
			||||||
 | 
							string parmsNodeTypeUpdateCacheRemove = string.Empty;
 | 
				
			||||||
 | 
							foreach (var uk001col in uk001) {
 | 
				
			||||||
 | 
								parmsBy += UString(uk001col.Name) + "And";
 | 
				
			||||||
 | 
								parmsNodeTypeUpdateCacheRemove += "item." + UString(uk001col.Name) + ", \"_,_\", ";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							parmsBy = parmsBy.Substring(0, parmsBy.Length - 3);
 | 
				
			||||||
 | 
							parmsNodeTypeUpdateCacheRemove = parmsNodeTypeUpdateCacheRemove.Substring(0, parmsNodeTypeUpdateCacheRemove.Length - 9);
 | 
				
			||||||
 | 
							redisRemoveCode += $@"
 | 
				
			||||||
 | 
									keys[keysIdx++] = string.Concat(""test:{table.Name}{(uk001[0].IsPrimary ? string.Empty : parmsBy)}:"", {parmsNodeTypeUpdateCacheRemove});";
 | 
				
			||||||
 | 
							%}{/for}
 | 
				
			||||||
 | 
							internal static void RemoveCache({#UString(table.Name)} item) => RemoveCache(item == null ? null : new [] { item });
 | 
				
			||||||
 | 
							internal static void RemoveCache(IEnumerable<{#UString(table.Name)}> items) {
 | 
				
			||||||
 | 
								if (ItemCacheTimeout <= 0 || items == null || items.Any() == false) return;
 | 
				
			||||||
 | 
								var keys = new string[items.Count() * {#table.Uniques.Count}];
 | 
				
			||||||
 | 
								var keysIdx = 0;
 | 
				
			||||||
 | 
								foreach (var item in items) {{#redisRemoveCode}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (freesql.Ado.TransactionCurrentThread != null) freesql.Ado.TransactionPreRemoveCache(keys);
 | 
				
			||||||
 | 
								else freesql.Cache.Remove(keys);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					{if (table.Columns.Count < 100)}{%
 | 
				
			||||||
 | 
							string CsParam3 = string.Empty;
 | 
				
			||||||
 | 
							string CsParamNoType3 = string.Empty;
 | 
				
			||||||
 | 
							string parms = string.Empty;
 | 
				
			||||||
 | 
							string parmsByWhereLambda = string.Empty;
 | 
				
			||||||
 | 
							string parmsNewItem = string.Empty;
 | 
				
			||||||
 | 
							string parmsBy = "By";
 | 
				
			||||||
 | 
							string parmsNoneType = string.Empty;
 | 
				
			||||||
 | 
							var idens = 0;
 | 
				
			||||||
 | 
							var idensCol = table.Columns[0];
 | 
				
			||||||
 | 
							foreach (var uk001col in table.Columns) {
 | 
				
			||||||
 | 
								string getcstype = GetCsType(uk001col);
 | 
				
			||||||
 | 
								parms += getcstype.Replace("?", "") + " " + UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
								if (uk001col.IsPrimary)
 | 
				
			||||||
 | 
									parmsByWhereLambda += "a." + UString(uk001col.Name) + " == " + UString(uk001col.Name) + " && ";
 | 
				
			||||||
 | 
								parmsNewItem += UString(uk001col.Name) + " = " + UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
								parmsBy += UString(uk001col.Name) + "And";
 | 
				
			||||||
 | 
								parmsNoneType += UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
								if (uk001col.IsIdentity) {
 | 
				
			||||||
 | 
									idens++;
 | 
				
			||||||
 | 
									idensCol = uk001col;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if (getcstype.StartsWith("DateTime") && (uk001col.Name.ToLower() == "create_time" || uk001col.Name.ToLower() == "update_time" || uk001col.Name.ToLower() == "createtime" || uk001col.Name.ToLower() == "updatetime") ||
 | 
				
			||||||
 | 
										getcstype == "bool?" && (uk001col.Name.ToLower() == "is_deleted" || uk001col.Name.ToLower() == "isdeleted")) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										CsParam3 += getcstype + " " + UString(uk001col.Name) + ", ";
 | 
				
			||||||
 | 
										CsParamNoType3 += string.Format("\r\n				{0} = {0}, ", UString(uk001col.Name));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							parms = parms.Substring(0, parms.Length - 2);
 | 
				
			||||||
 | 
							if (parmsByWhereLambda.Length > 0) parmsByWhereLambda = parmsByWhereLambda.Substring(0, parmsByWhereLambda.Length - 4);
 | 
				
			||||||
 | 
							parmsNewItem = parmsNewItem.Substring(0, parmsNewItem.Length - 2);
 | 
				
			||||||
 | 
							parmsBy = parmsBy.Substring(0, parmsBy.Length - 3);
 | 
				
			||||||
 | 
							parmsNoneType = parmsNoneType.Substring(0, parmsNoneType.Length - 2);
 | 
				
			||||||
 | 
							if (CsParam3.Length > 0) CsParam3 = CsParam3.Substring(0, CsParam3.Length - 2);
 | 
				
			||||||
 | 
							if (CsParamNoType3.Length > 0) CsParamNoType3 = CsParamNoType3.Substring(0, CsParamNoType3.Length - 2);
 | 
				
			||||||
 | 
							%}{if idens > 0}
 | 
				
			||||||
 | 
							public static {#GetCsType(idensCol)} Insert({#UString(table.Name)} item) {
 | 
				
			||||||
 | 
								item.{#UString(idensCol.Name)} = ({#GetCsType(idensCol)})freesql.Insert<{#UString(table.Name)}>().AppendData(item).ExecuteIdentity();
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(item);
 | 
				
			||||||
 | 
								return item.{#UString(idensCol.Name)};
 | 
				
			||||||
 | 
							}{else}
 | 
				
			||||||
 | 
							public static void Insert({#UString(table.Name)} item) {
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(item);
 | 
				
			||||||
 | 
								freesql.Insert<{#UString(table.Name)}>().AppendData(item).ExecuteAffrows();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							public static long Insert(IEnumerable<{#UString(table.Name)}> items) {
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(items);
 | 
				
			||||||
 | 
								return freesql.Insert<{#UString(table.Name)}>().AppendData(items).ExecuteAffrows();
 | 
				
			||||||
 | 
							}{/if}
 | 
				
			||||||
 | 
							{if CsParamNoType3.Split('=').Length <= 5}{if idens > 0}
 | 
				
			||||||
 | 
							public static {#GetCsType(idensCol)} Insert({#CsParam3}) {
 | 
				
			||||||
 | 
								var item = new {#UString(table.Name)} {{#CsParamNoType3}};
 | 
				
			||||||
 | 
								item.{#UString(idensCol.Name)} = ({#GetCsType(idensCol)})freesql.Insert<{#UString(table.Name)}>().AppendData(new {#UString(table.Name)} {{#CsParamNoType3}}).ExecuteIdentity();
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(item);
 | 
				
			||||||
 | 
								return item.{#UString(idensCol.Name)};
 | 
				
			||||||
 | 
							}{else}
 | 
				
			||||||
 | 
							public static {#UString(table.Name)} Insert({#CsParam3}) {
 | 
				
			||||||
 | 
								var item = new {#UString(table.Name)} {{#CsParamNoType3}};
 | 
				
			||||||
 | 
								freesql.Insert<{#UString(table.Name)}>().AppendData(item).ExecuteAffrows();
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(item);
 | 
				
			||||||
 | 
								return item;
 | 
				
			||||||
 | 
							}{/if}{/if}
 | 
				
			||||||
 | 
							public static long Update({#UString(table.Name)} item) {
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(item);
 | 
				
			||||||
 | 
								return freesql.Update<{#UString(table.Name)}>().SetSource(item).ExecuteAffrows();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							public static long Update(IEnumerable<{#UString(table.Name)}> items) {
 | 
				
			||||||
 | 
								if (ItemCacheTimeout > 0) RemoveCache(items);
 | 
				
			||||||
 | 
								return freesql.Update<{#UString(table.Name)}>().SetSource(items).ExecuteAffrows();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// 指定字段更新
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							public IUpdate<{#UString(table.Name)}> UpdateDiy => freesql.Update<{#UString(table.Name)}>().Where(a => {#parmsByWhereLambda});
 | 
				
			||||||
 | 
							/// <summary>
 | 
				
			||||||
 | 
							/// {if pks.Count > 0}保存或添加,如果主键有值则尝试 Update,如果影响的行为 0 则尝试 Insert{else}添加{/if}
 | 
				
			||||||
 | 
							/// </summary>
 | 
				
			||||||
 | 
							public void Save() {{if pks.Count > 0}
 | 
				
			||||||
 | 
								if ({#string.Join(" && ", pks.Select(pkssa => "this." + UString(pkssa.Name) + " != default(" + GetCsType(pkssa) + ")"))}) {
 | 
				
			||||||
 | 
									var affrows = freesql.Update<{#UString(table.Name)}>().Where(a => {#parmsByWhereLambda}).ExecuteAffrows();
 | 
				
			||||||
 | 
									if (affrows > 0) return;
 | 
				
			||||||
 | 
								}{/if}
 | 
				
			||||||
 | 
								{if idens > 0}this.{#UString(idensCol.Name)} = {#GetCsType(idensCol).Replace("?", "") == "long" ? "" : ("(" + GetCsType(idensCol) + ")")}freesql.Insert<{#UString(table.Name)}>().AppendData(this).ExecuteIdentity();{else}
 | 
				
			||||||
 | 
								freesql.Insert<{#UString(table.Name)}>().AppendData(this).ExecuteAffrows();{/if}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					{/if}{/if}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										94
									
								
								Templates/PostgreSQL/rich-entity-navigation-object/readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								Templates/PostgreSQL/rich-entity-navigation-object/readme.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					# 生成器
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					生成器是基于 dbfirst 开发的辅助工具,适用老项目一键生成实体。生成器采用模板的方式,作者实现了三种生成模板:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| 模板名称 | 类型映射 | 外键导航属性 | 缓存管理 | 失血 | 贫血 | 充血 |
 | 
				
			||||||
 | 
					| ------------- | - | - |- | - |- | - |
 | 
				
			||||||
 | 
					| simple-entity | √  | X | X | √ | X | X |
 | 
				
			||||||
 | 
					| simple-entity-navigation-object | √  | √ | X | √ | X | X |
 | 
				
			||||||
 | 
					| rich-entity-navigation-object | √  | √ | √ | X | √ | X |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					模板在项目目录:/Templates/MySql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 更多模板逐步开发中。。。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```csharp
 | 
				
			||||||
 | 
					//定义 mysql FreeSql
 | 
				
			||||||
 | 
					var 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=10")
 | 
				
			||||||
 | 
					    .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//创建模板生成类现实
 | 
				
			||||||
 | 
					var gen = new FreeSql.Generator.TemplateGenerator();
 | 
				
			||||||
 | 
					gen.Build(mysql.DbFirst, 
 | 
				
			||||||
 | 
					    @"C:\Users\28810\Desktop\github\FreeSql\Templates\MySql\simple-entity",  //模板目录(事先下载)
 | 
				
			||||||
 | 
					    @"C:\Users\28810\Desktop\新建文件夹 (9)",  //生成后保存的目录
 | 
				
			||||||
 | 
					    "cccddd" //数据库
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 模板语法
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					<title>{#title}</title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--绑定表达式-->
 | 
				
			||||||
 | 
					{#表达式}
 | 
				
			||||||
 | 
					{##表达式} 当表达式可能发生runtime错误时使用,性能没有上面的高
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--可嵌套使用,同一标签最多支持3个指令-->
 | 
				
			||||||
 | 
					{include ../header.html}
 | 
				
			||||||
 | 
					<div @for="i 1, 101">
 | 
				
			||||||
 | 
					  <p @if="i === 50" @for="item,index in data">aaa</p>
 | 
				
			||||||
 | 
					  <p @else="i % 3 === 0">bbb {#i}</p>
 | 
				
			||||||
 | 
					  <p @else="">ccc {#i}</p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--定义模块,可以将公共模块定义到一个文件中-->
 | 
				
			||||||
 | 
					{module module_name1 parms1, 2, 3...}
 | 
				
			||||||
 | 
					{/module}
 | 
				
			||||||
 | 
					{module module_name2 parms1, 2, 3...}
 | 
				
			||||||
 | 
					{/module}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--使用模块-->
 | 
				
			||||||
 | 
					{import ../module.html as myname}
 | 
				
			||||||
 | 
					{#myname.module_name(parms1, 2, 3...)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--继承-->
 | 
				
			||||||
 | 
					{extends ../inc/layout.html}
 | 
				
			||||||
 | 
					{block body}{/block}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--嵌入代码块-->
 | 
				
			||||||
 | 
					{%
 | 
				
			||||||
 | 
					for (var a = 0; a < 100; a++)
 | 
				
			||||||
 | 
					  print(a);
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--条件分支-->
 | 
				
			||||||
 | 
					{if i === 50}
 | 
				
			||||||
 | 
					{elseif i > 60}
 | 
				
			||||||
 | 
					{else}
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--三种循环-->
 | 
				
			||||||
 | 
					{for i 1,101}                可自定义名 {for index2 表达式1 in 表达式2}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{for item,index in items}    可选参数称 index
 | 
				
			||||||
 | 
					                             可自定义名 {for item2, index99 in 数组表达式}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{for key,item,index on json} 可选参数 item, index,
 | 
				
			||||||
 | 
					                             可自定义名 {for key2, item2, index99 in 对象表达式}
 | 
				
			||||||
 | 
					{/for}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--不被解析-->
 | 
				
			||||||
 | 
					{miss}
 | 
				
			||||||
 | 
					此块内容不被bmw.js解析
 | 
				
			||||||
 | 
					{/miss}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using FreeSql.DataAnnotations;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using Newtonsoft.Json.Linq;
 | 
				
			||||||
 | 
					using System.Net.NetworkInformation;
 | 
				
			||||||
 | 
					using NpgsqlTypes;
 | 
				
			||||||
 | 
					using Npgsql.LegacyPostgis;
 | 
				
			||||||
 | 
					{%
 | 
				
			||||||
 | 
					var dbf = dbfirst as FreeSql.IDbFirst;
 | 
				
			||||||
 | 
					var cols = (table.Columns as List<DbColumnInfo>);
 | 
				
			||||||
 | 
					var pks = (table.Primarys as List<DbColumnInfo>);
 | 
				
			||||||
 | 
					var fks = (table.Foreigns as List<DbForeignInfo>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Func<string, string> UString = stra => stra.Substring(0, 1).ToUpper() + stra.Substring(1);
 | 
				
			||||||
 | 
					Func<DbColumnInfo, string> GetCsType = cola3 => {
 | 
				
			||||||
 | 
						return dbf.GetCsType(cola3);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					Func<DbForeignInfo, string> GetFkObjectName = fkx => {
 | 
				
			||||||
 | 
						var eqfks = fks.Where(fk22a => fk22a.ReferencedTable.Name == fkx.ReferencedTable.Name);
 | 
				
			||||||
 | 
						if (eqfks.Count() == 1) return "Obj_" + fkx.ReferencedTable.Name;
 | 
				
			||||||
 | 
						var fkretname = fkx.Columns[0].Name;
 | 
				
			||||||
 | 
						if (fkretname.EndsWith(fkx.ReferencedColumns[0].Name, StringComparison.CurrentCultureIgnoreCase)) fkretname = fkretname.Substring(0, fkretname.Length - fkx.ReferencedColumns[0].Name.Length).TrimEnd('_');
 | 
				
			||||||
 | 
						if (fkretname.EndsWith(fkx.ReferencedTable.Name, StringComparison.CurrentCultureIgnoreCase)) fkretname = fkretname.Substring(0, fkretname.Length - fkx.ReferencedTable.Name.Length).TrimEnd('_');
 | 
				
			||||||
 | 
						if (fkretname.StartsWith(fkx.ReferencedTable.Name, StringComparison.CurrentCultureIgnoreCase)) fkretname = fkretname.Substring(fkx.ReferencedTable.Name.Length).TrimStart('_');
 | 
				
			||||||
 | 
						return "Obj_" + fkx.ReferencedTable.Name + (string.IsNullOrEmpty(fkretname) ? "" : ("_" + fkretname));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					namespace test.Model {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[JsonObject(MemberSerialization.OptIn), Table(Name = "{#!string.IsNullOrEmpty(table.Schema) ? table.Schema + "." : ""}{#table.Name}"{if cols.Where(cola003 => cola003.Name.ToLower() == "is_deleted" || cola003.Name.ToLower() == "isdeleted").Any()}, SelectFilter = "a.IsDeleted = 1"{/if})]
 | 
				
			||||||
 | 
						public partial class {#UString(table.Name)} {{for col,index in table.Columns}{%
 | 
				
			||||||
 | 
								var findfks = fks.Where(fkaa => fkaa.Columns.Where(fkaac1 => fkaac1.Name == col.Name).Any());
 | 
				
			||||||
 | 
							%}{if findfks.Any() == false}
 | 
				
			||||||
 | 
							{if string.IsNullOrEmpty(col.Coment) == false}/// <summary>
 | 
				
			||||||
 | 
							/// {#col.Coment.Replace("\r\n", "\n").Replace("\n", "\r\n		/// ")}
 | 
				
			||||||
 | 
							/// </summary>{/if}
 | 
				
			||||||
 | 
							[JsonProperty, Column(Name = "{#col.Name}", DbType = "{#col.DbTypeTextFull}"{if col.IsPrimary == true}, IsPrimary = true{/if}{if col.IsIdentity == true}, IsIdentity = true{/if}{if col.IsNullable == true}, IsNullable = true{/if})]
 | 
				
			||||||
 | 
							public {#GetCsType(col)} {#UString(col.Name)} { get; set; }
 | 
				
			||||||
 | 
							{else}
 | 
				
			||||||
 | 
							private {#GetCsType(col)} _{#UString(col.Name)};
 | 
				
			||||||
 | 
							{if string.IsNullOrEmpty(col.Coment) == false}/// <summary>
 | 
				
			||||||
 | 
							/// {#col.Coment.Replace("\r\n", "\n").Replace("\n", "\r\n		/// ")}
 | 
				
			||||||
 | 
							/// </summary>{/if}
 | 
				
			||||||
 | 
							[JsonProperty, Column(Name = "{#col.Name}", DbType = "{#col.DbTypeTextFull}"{if col.IsPrimary == true}, IsPrimary = true{/if}{if col.IsIdentity == true}, IsIdentity = true{/if}{if col.IsNullable == true}, IsNullable = true{/if})]
 | 
				
			||||||
 | 
							public {#GetCsType(col)} {#UString(col.Name)} { get => _{#UString(col.Name)}; set {
 | 
				
			||||||
 | 
								if (_{#UString(col.Name)} == value) return;
 | 
				
			||||||
 | 
								_{#UString(col.Name)} = value;{for fkcok2 in findfks}
 | 
				
			||||||
 | 
								{#GetFkObjectName(fkcok2)} = null;{/for}
 | 
				
			||||||
 | 
							} }
 | 
				
			||||||
 | 
							{/if}{/for}{for fk in fks}
 | 
				
			||||||
 | 
							public {#UString(fk.ReferencedTable.Name)} {#GetFkObjectName(fk)} { get; set; }
 | 
				
			||||||
 | 
							{/for}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					# 生成器
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					生成器是基于 dbfirst 开发的辅助工具,适用老项目一键生成实体。生成器采用模板的方式,作者实现了三种生成模板:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| 模板名称 | 类型映射 | 外键导航属性 | 缓存管理 | 失血 | 贫血 | 充血 |
 | 
				
			||||||
 | 
					| ------------- | - | - |- | - |- | - |
 | 
				
			||||||
 | 
					| simple-entity | √  | X | X | √ | X | X |
 | 
				
			||||||
 | 
					| simple-entity-navigation-object | √  | √ | X | √ | X | X |
 | 
				
			||||||
 | 
					| rich-entity-navigation-object | √  | √ | √ | X | √ | X |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					模板在项目目录:/Templates/MySql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 更多模板逐步开发中。。。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```csharp
 | 
				
			||||||
 | 
					//定义 mysql FreeSql
 | 
				
			||||||
 | 
					var 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=10")
 | 
				
			||||||
 | 
					    .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//创建模板生成类现实
 | 
				
			||||||
 | 
					var gen = new FreeSql.Generator.TemplateGenerator();
 | 
				
			||||||
 | 
					gen.Build(mysql.DbFirst, 
 | 
				
			||||||
 | 
					    @"C:\Users\28810\Desktop\github\FreeSql\Templates\MySql\simple-entity",  //模板目录(事先下载)
 | 
				
			||||||
 | 
					    @"C:\Users\28810\Desktop\新建文件夹 (9)",  //生成后保存的目录
 | 
				
			||||||
 | 
					    "cccddd" //数据库
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 模板语法
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					<title>{#title}</title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--绑定表达式-->
 | 
				
			||||||
 | 
					{#表达式}
 | 
				
			||||||
 | 
					{##表达式} 当表达式可能发生runtime错误时使用,性能没有上面的高
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--可嵌套使用,同一标签最多支持3个指令-->
 | 
				
			||||||
 | 
					{include ../header.html}
 | 
				
			||||||
 | 
					<div @for="i 1, 101">
 | 
				
			||||||
 | 
					  <p @if="i === 50" @for="item,index in data">aaa</p>
 | 
				
			||||||
 | 
					  <p @else="i % 3 === 0">bbb {#i}</p>
 | 
				
			||||||
 | 
					  <p @else="">ccc {#i}</p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--定义模块,可以将公共模块定义到一个文件中-->
 | 
				
			||||||
 | 
					{module module_name1 parms1, 2, 3...}
 | 
				
			||||||
 | 
					{/module}
 | 
				
			||||||
 | 
					{module module_name2 parms1, 2, 3...}
 | 
				
			||||||
 | 
					{/module}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--使用模块-->
 | 
				
			||||||
 | 
					{import ../module.html as myname}
 | 
				
			||||||
 | 
					{#myname.module_name(parms1, 2, 3...)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--继承-->
 | 
				
			||||||
 | 
					{extends ../inc/layout.html}
 | 
				
			||||||
 | 
					{block body}{/block}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--嵌入代码块-->
 | 
				
			||||||
 | 
					{%
 | 
				
			||||||
 | 
					for (var a = 0; a < 100; a++)
 | 
				
			||||||
 | 
					  print(a);
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--条件分支-->
 | 
				
			||||||
 | 
					{if i === 50}
 | 
				
			||||||
 | 
					{elseif i > 60}
 | 
				
			||||||
 | 
					{else}
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--三种循环-->
 | 
				
			||||||
 | 
					{for i 1,101}                可自定义名 {for index2 表达式1 in 表达式2}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{for item,index in items}    可选参数称 index
 | 
				
			||||||
 | 
					                             可自定义名 {for item2, index99 in 数组表达式}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{for key,item,index on json} 可选参数 item, index,
 | 
				
			||||||
 | 
					                             可自定义名 {for key2, item2, index99 in 对象表达式}
 | 
				
			||||||
 | 
					{/for}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--不被解析-->
 | 
				
			||||||
 | 
					{miss}
 | 
				
			||||||
 | 
					此块内容不被bmw.js解析
 | 
				
			||||||
 | 
					{/miss}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using FreeSql.DataAnnotations;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using Newtonsoft.Json.Linq;
 | 
				
			||||||
 | 
					using System.Net.NetworkInformation;
 | 
				
			||||||
 | 
					using NpgsqlTypes;
 | 
				
			||||||
 | 
					using Npgsql.LegacyPostgis;
 | 
				
			||||||
 | 
					{%
 | 
				
			||||||
 | 
					var dbf = dbfirst as FreeSql.IDbFirst;
 | 
				
			||||||
 | 
					var cols = (table.Columns as List<DbColumnInfo>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Func<string, string> UString = stra => stra.Substring(0, 1).ToUpper() + stra.Substring(1);
 | 
				
			||||||
 | 
					Func<DbColumnInfo, string> GetCsType = cola3 => {
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return dbf.GetCsType(cola3);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					namespace test.Model {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[JsonObject(MemberSerialization.OptIn), Table(Name = "{#!string.IsNullOrEmpty(table.Schema) ? table.Schema + "." : ""}{#table.Name}"{if cols.Where(cola003 => cola003.Name.ToLower() == "is_deleted" || cola003.Name.ToLower() == "isdeleted").Any()}, SelectFilter = "a.IsDeleted = 1"{/if})]
 | 
				
			||||||
 | 
						public partial class {#UString(table.Name)} {{for col,index in table.Columns}
 | 
				
			||||||
 | 
							{if string.IsNullOrEmpty(col.Coment) == false}/// <summary>
 | 
				
			||||||
 | 
							/// {#col.Coment.Replace("\r\n", "\n").Replace("\n", "\r\n		/// ")}
 | 
				
			||||||
 | 
							/// </summary>{/if}
 | 
				
			||||||
 | 
							[JsonProperty, Column(Name = "{#col.Name}", DbType = "{#col.DbTypeTextFull}"{if col.IsPrimary == true}, IsPrimary = true{/if}{if col.IsIdentity == true}, IsIdentity = true{/if}{if col.IsNullable == true}, IsNullable = true{/if})]
 | 
				
			||||||
 | 
							public {#GetCsType(col)} {#UString(col.Name)} { get; set; }
 | 
				
			||||||
 | 
							{/for}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										94
									
								
								Templates/PostgreSQL/simple-entity/readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								Templates/PostgreSQL/simple-entity/readme.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					# 生成器
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					生成器是基于 dbfirst 开发的辅助工具,适用老项目一键生成实体。生成器采用模板的方式,作者实现了三种生成模板:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| 模板名称 | 类型映射 | 外键导航属性 | 缓存管理 | 失血 | 贫血 | 充血 |
 | 
				
			||||||
 | 
					| ------------- | - | - |- | - |- | - |
 | 
				
			||||||
 | 
					| simple-entity | √  | X | X | √ | X | X |
 | 
				
			||||||
 | 
					| simple-entity-navigation-object | √  | √ | X | √ | X | X |
 | 
				
			||||||
 | 
					| rich-entity-navigation-object | √  | √ | √ | X | √ | X |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					模板在项目目录:/Templates/MySql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> 更多模板逐步开发中。。。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```csharp
 | 
				
			||||||
 | 
					//定义 mysql FreeSql
 | 
				
			||||||
 | 
					var 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=10")
 | 
				
			||||||
 | 
					    .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//创建模板生成类现实
 | 
				
			||||||
 | 
					var gen = new FreeSql.Generator.TemplateGenerator();
 | 
				
			||||||
 | 
					gen.Build(mysql.DbFirst, 
 | 
				
			||||||
 | 
					    @"C:\Users\28810\Desktop\github\FreeSql\Templates\MySql\simple-entity",  //模板目录(事先下载)
 | 
				
			||||||
 | 
					    @"C:\Users\28810\Desktop\新建文件夹 (9)",  //生成后保存的目录
 | 
				
			||||||
 | 
					    "cccddd" //数据库
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 模板语法
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					<title>{#title}</title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--绑定表达式-->
 | 
				
			||||||
 | 
					{#表达式}
 | 
				
			||||||
 | 
					{##表达式} 当表达式可能发生runtime错误时使用,性能没有上面的高
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--可嵌套使用,同一标签最多支持3个指令-->
 | 
				
			||||||
 | 
					{include ../header.html}
 | 
				
			||||||
 | 
					<div @for="i 1, 101">
 | 
				
			||||||
 | 
					  <p @if="i === 50" @for="item,index in data">aaa</p>
 | 
				
			||||||
 | 
					  <p @else="i % 3 === 0">bbb {#i}</p>
 | 
				
			||||||
 | 
					  <p @else="">ccc {#i}</p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--定义模块,可以将公共模块定义到一个文件中-->
 | 
				
			||||||
 | 
					{module module_name1 parms1, 2, 3...}
 | 
				
			||||||
 | 
					{/module}
 | 
				
			||||||
 | 
					{module module_name2 parms1, 2, 3...}
 | 
				
			||||||
 | 
					{/module}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--使用模块-->
 | 
				
			||||||
 | 
					{import ../module.html as myname}
 | 
				
			||||||
 | 
					{#myname.module_name(parms1, 2, 3...)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--继承-->
 | 
				
			||||||
 | 
					{extends ../inc/layout.html}
 | 
				
			||||||
 | 
					{block body}{/block}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--嵌入代码块-->
 | 
				
			||||||
 | 
					{%
 | 
				
			||||||
 | 
					for (var a = 0; a < 100; a++)
 | 
				
			||||||
 | 
					  print(a);
 | 
				
			||||||
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--条件分支-->
 | 
				
			||||||
 | 
					{if i === 50}
 | 
				
			||||||
 | 
					{elseif i > 60}
 | 
				
			||||||
 | 
					{else}
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--三种循环-->
 | 
				
			||||||
 | 
					{for i 1,101}                可自定义名 {for index2 表达式1 in 表达式2}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{for item,index in items}    可选参数称 index
 | 
				
			||||||
 | 
					                             可自定义名 {for item2, index99 in 数组表达式}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{for key,item,index on json} 可选参数 item, index,
 | 
				
			||||||
 | 
					                             可自定义名 {for key2, item2, index99 in 对象表达式}
 | 
				
			||||||
 | 
					{/for}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--不被解析-->
 | 
				
			||||||
 | 
					{miss}
 | 
				
			||||||
 | 
					此块内容不被bmw.js解析
 | 
				
			||||||
 | 
					{/miss}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										12
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								readme.md
									
									
									
									
									
								
							@@ -274,5 +274,17 @@ var t10 = fsql.Update<Topic>().SetRaw("Title = {0}", "新标题").Where("Id = {0
 | 
				
			|||||||
# Part5 表达式函数
 | 
					# Part5 表达式函数
 | 
				
			||||||
详情查看:[《Expression 表达式函数》](Docs/expression.md)
 | 
					详情查看:[《Expression 表达式函数》](Docs/expression.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Part6 事务
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```csharp
 | 
				
			||||||
 | 
					fsql.Transaction(() => {
 | 
				
			||||||
 | 
					     //code
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					没异常就提交,有异常会回滚。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					代码体内只可以使用同步方法,因为事务对象挂靠在线程关联上,使用异步方法会切换线程。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 贡献者名单
 | 
					## 贡献者名单
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user