initial commit

This commit is contained in:
tk
2024-11-13 18:18:28 +08:00
commit 013f35e296
1500 changed files with 443723 additions and 0 deletions

View File

@ -0,0 +1,354 @@
using FreeSql.DatabaseModel;
using RazorEngine.Templating;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Console = Colorful.Console;
namespace FreeSql.Generator
{
class ConsoleApp
{
string ArgsRazorRaw { get; }
string ArgsRazor { get; }
bool[] ArgsNameOptions { get; }
string ArgsNameSpace { get; }
DataType ArgsDbType { get; }
string ArgsConnectionString { get; }
string ArgsFilter { get; }
string ArgsMatch { get; }
string ArgsJson { get; }
string ArgsFileName { get; }
bool ArgsReadKey { get; }
internal string ArgsOutput { get; private set; }
public ConsoleApp(string[] args, ManualResetEvent wait)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
//var gb2312 = Encoding.GetEncoding("GB2312");
//if (gb2312 != null)
//{
// try
// {
// Console.OutputEncoding = gb2312;
// Console.InputEncoding = gb2312;
// }
// catch { }
//}
//var ntjson = Assembly.LoadFile(@"C:\Users\28810\Desktop\testfreesql\bin\Debug\netcoreapp2.2\publish\testfreesql.dll");
//using (var gen = new Generator(new GeneratorOptions()))
//{
// gen.TraceLog = log => Console.WriteFormatted(log + "\r\n", Color.DarkGray);
// gen.Build(ArgsOutput, new[] { typeof(ojbk.Entities.AuthRole) }, false);
//}
var version = "v" + string.Join(".", typeof(ConsoleApp).Assembly.GetName().Version.ToString().Split('.').Where((a, b) => b <= 2));
Console.WriteAscii(" FreeSql", Color.Violet);
Console.WriteFormatted(@"
# Github # {0} {1}
", Color.SlateGray,
new Colorful.Formatter("https://github.com/2881099/FreeSql", Color.DeepSkyBlue),
new Colorful.Formatter("v" + string.Join(".", typeof(ConsoleApp).Assembly.GetName().Version.ToString().Split('.').Where((a, b) => b <= 2)), Color.SlateGray));
ArgsRazorRaw = "1";
ArgsRazor = RazorContentManager._特性_cshtml;
ArgsNameOptions = new[] { false, false, false, false };
ArgsNameSpace = "MyProject";
ArgsFilter = "";
ArgsMatch = "";
ArgsJson = "Newtonsoft.Json";
ArgsFileName = "{name}.cs";
ArgsReadKey = true;
Action<string> setArgsOutput = value =>
{
ArgsOutput = value;
ArgsOutput = ArgsOutput.Trim().TrimEnd('/', '\\');
ArgsOutput += ArgsOutput.Contains("\\") ? "\\" : "/";
if (!Directory.Exists(ArgsOutput))
Directory.CreateDirectory(ArgsOutput);
};
setArgsOutput(Directory.GetCurrentDirectory());
string args0 = args[0].Trim().ToLower();
if (args[0] == "?" || args0 == "--help" || args0 == "-help")
{
Console.WriteFormatted(@"
{0}
更新工具dotnet tool update -g FreeSql.Generator
# 快速开始 #
> {1} {2} 1 {3} 0,0,0,0 {4} MyProject {5} ""MySql,Data Source=127.0.0.1;...""
-Razor 1 * 选择模板:实体类+特性
-Razor 2 * 选择模板:实体类+特性+导航属性
-Razor ""d:\diy.cshtml"" * 自定义模板文件如乱码请修改为UTF8(不带BOM)编码格式
-NameOptions * 4个布尔值对应
首字母大写
首字母大写,其他小写
全部小写
下划线转驼峰
-NameSpace * 命名空间
-DB ""{6},data source=127.0.0.1;port=3306;user id=root;password=root;initial catalog=数据库;charset=utf8;sslmode=none;max pool size=2""
-DB ""{7},data source=.;integrated security=True;initial catalog=数据库;pooling=true;max pool size=2""
-DB ""{8},host=127.0.0.1;port=5432;username=postgres;password=123456;database=数据库;pooling=true;maximum pool size=2""
-DB ""{9},user id=user1;password=123456;data source=//127.0.0.1:1521/XE;pooling=true;max pool size=2""
-DB ""{10},data source=document.db""
-DB ""{14},database=localhost:D:\fbdata\EXAMPLES.fdb;user=sysdba;password=123456;max pool size=2""
-DB ""{11},server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user;poolsize=2""
-DB ""{12},server=127.0.0.1;port=54321;uid=USER2;pwd=123456789;database=数据库""
-DB ""{13},host=127.0.0.1;port=2003;database=数据库;username=SYSDBA;password=szoscar55;maxpoolsize=2""
* {11}(达梦数据库)、{12}(人大金仓数据库)、{13}(神舟通用数据库)
-Filter Table+View+StoreProcedure
默认生成:表+视图+存储过程
如果不想生成视图和存储过程 -Filter View+StoreProcedure
-Match 表名或正则表达式只生成匹配的表dbo\.TB_.+
-Json NTJ、STJ、NONE
Newtonsoft.Json、System.Text.Json、不生成
-FileName 文件名,默认:{name}.cs
-Output 保存路径,默认为当前 shell 所在目录
{15}
", Color.SlateGray,
new Colorful.Formatter("FreeSql 快速生成数据库的实体类", Color.SlateGray),
new Colorful.Formatter("FreeSql.Generator", Color.White),
new Colorful.Formatter("-Razor", Color.ForestGreen),
new Colorful.Formatter("-NameOptions", Color.ForestGreen),
new Colorful.Formatter("-NameSpace", Color.ForestGreen),
new Colorful.Formatter("-DB", Color.ForestGreen),
new Colorful.Formatter("MySql", Color.Yellow),
new Colorful.Formatter("SqlServer", Color.Yellow),
new Colorful.Formatter("PostgreSQL", Color.Yellow),
new Colorful.Formatter("Oracle", Color.Yellow),
new Colorful.Formatter("Sqlite", Color.Yellow),
new Colorful.Formatter("Dameng", Color.Yellow),
new Colorful.Formatter("KingbaseES", Color.Yellow),
new Colorful.Formatter("ShenTong", Color.Yellow),
new Colorful.Formatter("Firebird", Color.Yellow),
new Colorful.Formatter("推荐在实体类目录创建 gen.bat双击它重新所有实体类", Color.ForestGreen)
);
wait.Set();
return;
}
for (int a = 0; a < args.Length; a++)
{
switch (args[a].Trim().ToLower())
{
case "-razor":
ArgsRazorRaw = args[a + 1].Trim();
switch (ArgsRazorRaw)
{
case "1": ArgsRazor = RazorContentManager._特性_cshtml; break;
case "2": ArgsRazor = RazorContentManager._特性_导航属性_cshtml; break;
default: ArgsRazor = File.ReadAllText(args[a + 1], Encoding.UTF8); break;
}
a++;
break;
case "-nameoptions":
ArgsNameOptions = args[a + 1].Split(',').Select(opt => opt == "1").ToArray();
if (ArgsNameOptions.Length != 4) throw new ArgumentException(CoreStrings.S_NameOptions_Incorrect);
a++;
break;
case "-namespace":
ArgsNameSpace = args[a + 1];
a++;
break;
case "-db":
var dbargs = args[a + 1].Split(',', 2);
if (dbargs.Length != 2) throw new ArgumentException(CoreStrings.S_DB_ParameterError);
switch (dbargs[0].Trim().ToLower())
{
case "mysql": ArgsDbType = DataType.MySql; break;
case "sqlserver": ArgsDbType = DataType.SqlServer; break;
case "postgresql": ArgsDbType = DataType.PostgreSQL; break;
case "oracle": ArgsDbType = DataType.Oracle; break;
case "sqlite": ArgsDbType = DataType.Sqlite; break;
case "firebird": ArgsDbType = DataType.Firebird; break;
case "dameng": ArgsDbType = DataType.Dameng; break;
case "kingbasees": ArgsDbType = DataType.KingbaseES; break;
case "shentong": ArgsDbType = DataType.ShenTong; break;
case "clickhouse": ArgsDbType = DataType.ClickHouse; break;
default: throw new ArgumentException(CoreStrings.S_DB_ParameterError_UnsupportedType(dbargs[0]));
}
ArgsConnectionString = dbargs[1].Trim();
a++;
break;
case "-filter":
ArgsFilter = args[a + 1];
a++;
break;
case "-match":
ArgsMatch = args[a + 1];
if (Regex.IsMatch("", ArgsMatch)) { } //throw
a++;
break;
case "-json":
switch(args[a + 1].Trim().ToLower())
{
case "none":
ArgsJson = "";
break;
case "stj":
ArgsJson = "System.Text.Json";
break;
}
a++;
break;
case "-filename":
ArgsFileName = args[a + 1];
a++;
break;
case "-readkey":
ArgsReadKey = args[a + 1].Trim() == "1";
a++;
break;
case "-output":
setArgsOutput(args[a + 1]);
a++;
break;
default:
throw new ArgumentException(CoreStrings.S_WrongParameter(args[a]));
}
}
if (string.IsNullOrEmpty(ArgsConnectionString)) throw new ArgumentException(CoreStrings.S_DB_Parameter_Error_NoConnectionString);
RazorEngine.Engine.Razor = RazorEngineService.Create(new RazorEngine.Configuration.TemplateServiceConfiguration
{
EncodedStringFactory = new RazorEngine.Text.RawStringFactory() // Raw string encoding.
});
var razorId = Guid.NewGuid().ToString("N");
RazorEngine.Engine.Razor.Compile(ArgsRazor, razorId);
var outputCounter = 0;
using (IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(ArgsDbType, ArgsConnectionString)
.UseAutoSyncStructure(false)
.UseMonitorCommand(cmd => Console.WriteFormatted(cmd.CommandText + "\r\n", Color.SlateGray))
.Build())
{
List<DbTableInfo> tables = new List<DbTableInfo>();
if (string.IsNullOrEmpty(ArgsMatch) == false)
{
try
{
var matchTable = fsql.DbFirst.GetTableByName(ArgsMatch);
if (matchTable != null) tables.Add(matchTable);
}
catch { }
}
if (tables.Any() == false)
tables = fsql.DbFirst.GetTablesByDatabase();
var outputTables = tables;
//开始生成操作
foreach (var table in outputTables)
{
if (string.IsNullOrEmpty(ArgsMatch) == false)
{
if (Regex.IsMatch($"{table.Schema}.{table.Name}".TrimStart('.'), ArgsMatch) == false) continue;
}
switch (table.Type)
{
case DatabaseModel.DbTableType.TABLE:
if (ArgsFilter.Contains("Table", StringComparison.OrdinalIgnoreCase))
{
Console.WriteFormatted(" Ignore Table -> " + table.Name + "\r\n", Color.DarkSlateGray);
continue;
}
break;
case DatabaseModel.DbTableType.VIEW:
if (ArgsFilter.Contains("View", StringComparison.OrdinalIgnoreCase))
{
Console.WriteFormatted(" Ignore View -> " + table.Name + "\r\n", Color.DarkSlateGray);
continue;
}
break;
case DatabaseModel.DbTableType.StoreProcedure:
if (ArgsFilter.Contains("StoreProcedure", StringComparison.OrdinalIgnoreCase))
{
Console.WriteFormatted(" Ignore StoreProcedure -> " + table.Name + "\r\n", Color.DarkSlateGray);
continue;
}
break;
}
var sw = new StringWriter();
var model = new RazorModel(fsql, ArgsNameSpace, ArgsNameOptions, tables, table);
RazorEngine.Engine.Razor.Run(razorId, sw, null, model);
StringBuilder plus = new StringBuilder();
//plus.AppendLine("//------------------------------------------------------------------------------");
//plus.AppendLine("// <auto-generated>");
//plus.AppendLine("// 此代码由工具 FreeSql.Generator 生成。");
//plus.AppendLine("// 运行时版本:" + Environment.Version.ToString());
//plus.AppendLine("// Website: https://github.com/2881099/FreeSql");
//plus.AppendLine("// 对此文件的更改可能会导致不正确的行为,并且如果");
//plus.AppendLine("// 重新生成代码,这些更改将会丢失。");
//plus.AppendLine("// </auto-generated>");
//plus.AppendLine("//------------------------------------------------------------------------------");
plus.Append(sw.ToString());
plus.AppendLine();
var outputFile = $"{ArgsOutput}{ArgsFileName.Replace("{name}", model.GetCsName(table.Name))}";
File.WriteAllText(outputFile, plus.ToString(), Encoding.UTF8);
switch (table.Type)
{
case DatabaseModel.DbTableType.TABLE:
Console.WriteFormatted(" OUT Table -> " + outputFile + "\r\n", Color.DeepSkyBlue);
break;
case DatabaseModel.DbTableType.VIEW:
Console.WriteFormatted(" OUT View -> " + outputFile + "\r\n", Color.DeepSkyBlue);
break;
case DatabaseModel.DbTableType.StoreProcedure:
Console.WriteFormatted(" OUT StoreProcedure -> " + outputFile + "\r\n", Color.DeepSkyBlue);
break;
}
++outputCounter;
}
}
var rebuildBat = ArgsOutput + "__重新生成.bat";
if (File.Exists(rebuildBat) == false)
{
var razorCshtml = ArgsOutput + "__razor.cshtml.txt";
if (File.Exists(razorCshtml) == false)
{
File.WriteAllText(razorCshtml, ArgsRazor, Encoding.UTF8);
Console.WriteFormatted(" OUT -> " + razorCshtml + " (以后) 编辑它自定义模板生成\r\n", Color.Magenta);
++outputCounter;
}
File.WriteAllText(rebuildBat, $@"
FreeSql.Generator -Razor ""__razor.cshtml.txt"" -NameOptions {string.Join(",", ArgsNameOptions.Select(a => a ? 1 : 0))} -NameSpace {ArgsNameSpace} -DB ""{ArgsDbType},{ArgsConnectionString}""{(string.IsNullOrEmpty(ArgsFilter) ? "" : $" -Filter \"{ArgsFilter}\"")}{(string.IsNullOrEmpty(ArgsMatch) ? "" : $" -Match \"{ArgsMatch}\"")} -FileName ""{ArgsFileName}""
", Encoding.UTF8);
Console.WriteFormatted(" OUT -> " + rebuildBat + " (以后) 双击它重新生成实体\r\n", Color.Magenta);
++outputCounter;
}
Console.WriteFormatted($"\r\n[{DateTime.Now.ToString("MM-dd HH:mm:ss")}] 生成完毕,总共生成了 {outputCounter} 个文件,目录:\"{ArgsOutput}\"\r\n", Color.DarkGreen);
if (ArgsReadKey)
Console.ReadKey();
wait.Set();
}
}
}

View File

@ -0,0 +1,60 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net60</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPackable>true</IsPackable>
<PackAsTool>true</PackAsTool>
<Authors>FreeSql;ncc;YeXiangQin</Authors>
<Company>2881099</Company>
<Product>FreeSql</Product>
<Description>使用 FreeSql 快速生成数据库的实体类安装dotnet tool install -g FreeSql.Generator</Description>
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
<PackageTags>FreeSql DbFirst 实体生成器</PackageTags>
<Version>3.2.833</Version>
<PackageReadmeFile>readme.md</PackageReadmeFile>
</PropertyGroup>
<ItemGroup>
<None Include="../../readme.md" Pack="true" PackagePath="\"/>
<None Include="../../logo.png" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Colorful.Console" Version="1.2.9" />
<PackageReference Include="RazorEngine.NetCore" Version="2.2.6" />
<PackageReference Include="System.CodeDom" Version="6.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="DmProvider">
<HintPath>..\..\Providers\FreeSql.Provider.Dameng\lib\DmProvider\netstandard2.0\DmProvider.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Data.OscarClient">
<HintPath>..\..\Providers\FreeSql.Provider.ShenTong\lib\System.Data.OscarClient.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Reference Include="Kdbndp">
<HintPath>..\..\Providers\FreeSql.Provider.KingbaseES\lib\Kdbndp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Dameng\FreeSql.Provider.Dameng.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Firebird\FreeSql.Provider.Firebird.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.KingbaseES\FreeSql.Provider.KingbaseES.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.ShenTong\FreeSql.Provider.ShenTong.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace FreeSql.Generator
{
public class Program
{
static void Main(string[] args)
{
if (args != null && args.Length == 0) args = new[] { "?" };
ManualResetEvent wait = new ManualResetEvent(false);
new Thread(() => {
Thread.CurrentThread.Join(TimeSpan.FromSeconds(1));
ConsoleApp app = new ConsoleApp(args, wait);
}).Start();
wait.WaitOne();
return;
}
}
}

View File

@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace FreeSql.Generator
{
class RazorContentManager
{
public static string _特性_cshtml =
#region
@"using FreeSql.DatabaseModel;@{
var gen = Model as RazorModel;
Func<string, string> GetAttributeString = attr => {
if (string.IsNullOrEmpty(attr)) return """";
return string.Concat("", "", attr.Trim('[', ']'));
};
Func<string, string> GetDefaultValue = defval => {
if (string.IsNullOrEmpty(defval)) return """";
return "" = "" + defval + "";"";
};
}@{
switch (gen.fsql.Ado.DataType) {
case FreeSql.DataType.PostgreSQL:
@: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;
break;
case FreeSql.DataType.SqlServer:
case FreeSql.DataType.MySql:
default:
@: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;
break;
}
}
namespace @gen.NameSpace {
@if (string.IsNullOrEmpty(gen.table.Comment) == false) {
@:/// <summary>
@:/// @gen.table.Comment.Replace(""\r\n"", ""\n"").Replace(""\n"", ""\r\n /// "")
@:/// </summary>
}
[JsonObject(MemberSerialization.OptIn)@GetAttributeString(gen.GetTableAttribute())]
public partial class @gen.GetCsName(gen.FullTableName) {
@foreach (var col in gen.columns) {
if (string.IsNullOrEmpty(col.Comment) == false) {
@:/// <summary>
@:/// @col.Comment.Replace(""\r\n"", ""\n"").Replace(""\n"", ""\r\n /// "")
@:/// </summary>
}
@:@(""[JsonProperty"" + GetAttributeString(gen.GetColumnAttribute(col, true)) + ""]"")
@:public @gen.GetCsType(col) @gen.GetCsName(col.Name) { get; set; }@GetDefaultValue(gen.GetColumnDefaultValue(col, false))
@:
}
}
@gen.GetMySqlEnumSetDefine()
}";
#endregion
public static string _特性_导航属性_cshtml =
#region
@"@using FreeSql.DatabaseModel;@{
var isLazying = true; //延时加载
var isOneToMany = true; //一对多,集合属性
var isManyToMany = true; //多对多,集合属性
var gen = Model as RazorModel;
var fks = gen.table.Foreigns;
Func<string, string> GetAttributeString = attr => {
if (string.IsNullOrEmpty(attr)) return """";
return string.Concat("", "", attr.Trim('[', ']'));
};
Func<string, string> GetDefaultValue = defval => {
if (string.IsNullOrEmpty(defval)) return """";
return "" = "" + defval + "";"";
};
Func<DbForeignInfo, string> GetFkObjectName = fkx => {
var eqfks = fks.Where(fk22a => fk22a.ReferencedTable.Name == fkx.ReferencedTable.Name);
if (eqfks.Count() == 1) return 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 fkx.ReferencedTable.Name + (string.IsNullOrEmpty(fkretname) ? """" : (""_"" + fkretname));
};
Func<DbForeignInfo, string> GetFkObjectNameOutside = fkx => {
var eqfks = fkx.Table.Foreigns.Where(fk22a => fk22a.ReferencedTable.Name == fkx.ReferencedTable.Name);
if (eqfks.Count() == 1) return fkx.Table.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 fkx.Table.Name + (string.IsNullOrEmpty(fkretname) ? """" : (""_"" + fkretname));
};
}@{
switch (gen.fsql.Ado.DataType) {
case FreeSql.DataType.PostgreSQL:
@:using System;
@:using System.Collections.Generic;
@:using Newtonsoft.Json;
@:using FreeSql.DataAnnotations;
@:using System.Net;
@:using Newtonsoft.Json.Linq;
@:using System.Net.NetworkInformation;
@:using NpgsqlTypes;
@:using Npgsql.LegacyPostgis;
break;
case FreeSql.DataType.SqlServer:
case FreeSql.DataType.MySql:
default:
@:using System;
@:using System.Collections.Generic;
@:using Newtonsoft.Json;
@:using FreeSql.DataAnnotations;
break;
}
}
namespace @gen.NameSpace {
@if (string.IsNullOrEmpty(gen.table.Comment) == false) {
@:/// <summary>
@:/// @gen.table.Comment.Replace(""\r\n"", ""\n"").Replace(""\n"", ""\r\n /// "")
@:/// </summary>
}
[JsonObject(MemberSerialization.OptIn)@GetAttributeString(gen.GetTableAttribute())]
public partial class @gen.GetCsName(gen.FullTableName) {
@foreach (var col in gen.columns) {
var findfks = fks.Where(fkaa => fkaa.Columns.Where(fkaac1 => fkaac1.Name == col.Name).Any());
var csname = gen.GetCsName(col.Name);
if (string.IsNullOrEmpty(col.Comment) == false) {
@:/// <summary>
@:/// @col.Comment.Replace(""\r\n"", ""\n"").Replace(""\n"", ""\r\n /// "")
@:/// </summary>
}
@:@(""[JsonProperty"" + GetAttributeString(gen.GetColumnAttribute(col, true)) + ""]"")
if (findfks.Any() == false) {
@:public @gen.GetCsType(col) @csname { get; set; }@GetDefaultValue(gen.GetColumnDefaultValue(col, false))
} else {
@:public @gen.GetCsType(col) @csname { get => _@csname; set {
@:if (_@csname == value) return;
@:_@csname = value;
foreach (var fkcok2 in findfks) {
@:@gen.GetCsName(GetFkObjectName(fkcok2)) = null;
}
@:} }
@:private @gen.GetCsType(col) _@csname@GetDefaultValue(gen.GetColumnDefaultValue(col, false)).TrimEnd(';');
}
@:
}
@if (fks.Any()) {
@:
@:#region 外键 => 导航属性ManyToOne/OneToOne
foreach (var fk in fks) {
var fkTableName = (fk.ReferencedTable.Schema + ""."" + fk.ReferencedTable.Name).Trim('.');
if (fk.ReferencedTable.Schema == ""public"" || fk.ReferencedTable.Schema == ""dbo"")
{
fkTableName = fkTableName.Replace(fk.ReferencedTable.Schema + ""."", """");
}
@:
@:[Navigate(""@string.Join("", "", fk.Columns.Select(a => gen.GetCsName(a.Name)))"")]
@:public@(isLazying ? "" virtual"" : """") @gen.GetCsName(fkTableName) @gen.GetCsName(GetFkObjectName(fk)) { get; set; }
}
@:
@:#endregion
}
@if (isOneToMany && gen.tables.Where(tmpft => tmpft.Foreigns.Where(tmpftfk => tmpftfk.ReferencedTable.Schema == gen.table.Schema && tmpftfk.ReferencedTable.Name == gen.table.Name && tmpftfk.Columns.Where(tmpcol => tmpcol.IsPrimary).Count() != tmpftfk.Columns.Count).Any()).Any()) {
@:
@:#region 外键 => 导航属性OneToMany
foreach (var ft in gen.tables) {
var ftfks = ft.Foreigns.Where(ftfk => ftfk.ReferencedTable.Schema == gen.table.Schema && ftfk.ReferencedTable.Name == gen.table.Name && ftfk.Columns.Where(tmpcol => tmpcol.IsPrimary).Count() != ftfk.Columns.Count).ToArray();
foreach (var fk in ftfks) {
var fkTableName = (ft.Schema + ""."" + ft.Name).Trim('.');
if (ft.Schema == ""public"" || ft.Schema == ""dbo"")
{
fkTableName = fkTableName.Replace(ft.Schema + ""."", """");
}
@:
@:[Navigate(""@string.Join("", "", fk.Columns.Select(a => gen.GetCsName(a.Name)))"")]
@:public@(isLazying ? "" virtual"" : """") List<@gen.GetCsName(fkTableName)> @gen.GetCsName(GetFkObjectNameOutside(fk))s { get; set; }
}
}
@:
@:#endregion
}
@if (isManyToMany) {
var manyAny = false;
foreach (var ft in gen.tables) {
if (ft != gen.table) {
var ftfks = ft.Foreigns.Where(ftfk => ftfk.Columns.Where(ftfkcol => ftfkcol.IsPrimary == false).Any() == false).ToArray();
if (ftfks.Length == 2) {
var fk1 = ftfks.Where(ftfk => (ftfk.ReferencedTable.Schema + ""."" + ftfk.ReferencedTable.Name).Trim('.') == gen.FullTableName).ToArray();
if (fk1.Length == 1) {
var fk2 = ftfks.Where(ftfk => fk1.Contains(ftfk) == false).ToArray();
var midft = ft;
var leftft = gen.table;
DbTableInfo rightft = null;
if (fk2.Any()) {
rightft = fk2[0].ReferencedTable;
} else {
rightft = fk1[1].ReferencedTable;
}
var fkTableName = (rightft.Schema + ""."" + rightft.Name).Trim('.');
if (rightft.Schema == ""public"" || rightft.Schema == ""dbo"")
{
fkTableName = fkTableName.Replace(rightft.Schema + ""."", """");
}
var middleTableName = (midft.Schema + ""."" + midft.Name).Trim('.');
if (midft.Schema == ""public"" || midft.Schema == ""dbo"")
{
middleTableName = middleTableName.Replace(midft.Schema + ""."", """");
}
var csname = rightft.Name;
if (manyAny == false)
{
manyAny = true;
@:
@:#region 外键 => 导航属性ManyToMany
}
@:
@:[Navigate(ManyToMany = typeof(@gen.GetCsName(middleTableName)))]
@:public@(isLazying ? "" virtual"" : """") List<@gen.GetCsName(fkTableName)> @gen.GetCsName(csname)s { get; set; }
}
}
}
}
if (manyAny)
{
@:
@:#endregion
}
}
}
@gen.GetMySqlEnumSetDefine()
}";
#endregion
}
}

View File

@ -0,0 +1,344 @@
using FreeSql;
using FreeSql.DataAnnotations;
using FreeSql.DatabaseModel;
using FreeSql.Internal.CommonProvider;
using MySqlConnector;
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
public class RazorModel
{
public RazorModel(IFreeSql fsql, string nameSpace, bool[] NameOptions, List<DbTableInfo> tables, DbTableInfo table)
{
this.fsql = fsql;
this.NameSpace = nameSpace;
this.NameOptions = NameOptions;
this.tables = tables;
this.table = table;
}
public IFreeSql fsql { get; set; }
public bool[] NameOptions { get; set; }
public List<DbTableInfo> tables { get; set; }
public DbTableInfo table { get; set; }
public List<DbColumnInfo> columns => this.table.Columns;
public string NameSpace { get; set; }
public string FullTableName => $"{(new[] { "public", "dbo" }.Contains(table.Schema) ? "" : table.Schema)}.{table.Name}".TrimStart('.');
public string GetCsName(string name)
{
name = Regex.Replace(name.TrimStart('@', '.'), @"[^\w]", "_");
name = char.IsLetter(name, 0) ? name : string.Concat("_", name);
if (NameOptions[0]) name = UFString(name);
if (NameOptions[1]) name = UFString(name.ToLower());
if (NameOptions[2]) name = name.ToLower();
if (NameOptions[3]) name = string.Join("", name.Split('_').Select(a => UFString(a)));
return name;
}
public string UFString(string text)
{
text = Regex.Replace(text, @"[^\w]", "_");
if (text.Length <= 1) return text.ToUpper();
else return text.Substring(0, 1).ToUpper() + text.Substring(1, text.Length - 1);
}
public string LFString(string text)
{
text = Regex.Replace(text, @"[^\w]", "_");
if (text.Length <= 1) return text.ToLower();
else return text.Substring(0, 1).ToLower() + text.Substring(1, text.Length - 1);
}
private string LiteralString(string text)
{
using (var writer = new StringWriter())
{
using (var provider = CodeDomProvider.CreateProvider("CSharp"))
{
provider.GenerateCodeFromExpression(new CodePrimitiveExpression(text), writer, null);
return writer.ToString();
}
}
}
public string GetCsType(DbColumnInfo col)
{
if (fsql.Ado.DataType == FreeSql.DataType.MySql)
if (col.DbType == (int)MySqlDbType.Enum || col.DbType == (int)MySqlDbType.Set)
return $"{this.GetCsName(this.FullTableName)}{this.GetCsName(col.Name).ToUpper()}{(col.IsNullable ? "?" : "")}";
return fsql.DbFirst.GetCsType(col);
}
#region
public string GetTableAttribute()
{
var sb = new List<string>();
if (GetCsName(this.FullTableName) != this.FullTableName)
{
if (this.FullTableName.IndexOf('.') == -1)
sb.Add("Name = \"" + this.FullTableName + "\"");
else
sb.Add("Name = \"" + this.FullTableName + "\""); //Todo: QuoteSqlName
}
sb.Add("DisableSyncStructure = true");
if (sb.Any() == false) return null;
return "[Table(" + string.Join(", ", sb) + ")]";
}
public string GetColumnAttribute(DbColumnInfo col, bool isInsertValueSql = false)
{
var sb = new List<string>();
if (GetCsName(col.Name) != col.Name)
sb.Add("Name = \"" + col.Name + "\"");
if (col.CsType != null)
{
var dbinfo = fsql.CodeFirst.GetDbInfo(col.CsType);
if (dbinfo != null && string.Compare(dbinfo.dbtypeFull.Replace("NOT NULL", "").Trim(), col.DbTypeTextFull, true) != 0)
{
#region StringLength
switch (fsql.Ado.DataType)
{
case DataType.MySql:
case DataType.OdbcMySql:
switch (col.DbTypeTextFull.ToLower())
{
case "longtext": sb.Add("StringLength = -2"); break;
case "text": sb.Add("StringLength = -1"); break;
default:
var m_stringLength = Regex.Match(col.DbTypeTextFull, @"^varchar\s*\((\w+)\)$", RegexOptions.IgnoreCase);
if (m_stringLength.Success) sb.Add($"StringLength = {m_stringLength.Groups[1].Value}");
else sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
break;
}
break;
case DataType.SqlServer:
case DataType.OdbcSqlServer:
switch (col.DbTypeTextFull.ToLower())
{
case "nvarchar(max)": sb.Add("StringLength = -2"); break;
default:
var m_stringLength = Regex.Match(col.DbTypeTextFull, @"^nvarchar\s*\((\w+)\)$", RegexOptions.IgnoreCase);
if (m_stringLength.Success) sb.Add($"StringLength = {m_stringLength.Groups[1].Value}");
else sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
break;
}
break;
case DataType.PostgreSQL:
case DataType.OdbcPostgreSQL:
case DataType.KingbaseES:
case DataType.OdbcKingbaseES:
case DataType.ShenTong:
switch (col.DbTypeTextFull.ToLower())
{
case "text": sb.Add("StringLength = -2"); break;
default:
var m_stringLength = Regex.Match(col.DbTypeTextFull, @"^varchar\s*\((\w+)\)$", RegexOptions.IgnoreCase);
if (m_stringLength.Success) sb.Add($"StringLength = {m_stringLength.Groups[1].Value}");
else sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
break;
}
break;
case DataType.Oracle:
case DataType.OdbcOracle:
switch (col.DbTypeTextFull.ToLower())
{
case "nclob": sb.Add("StringLength = -2"); break;
default:
var m_stringLength = Regex.Match(col.DbTypeTextFull, @"^nvarchar2\s*\((\w+)\)$", RegexOptions.IgnoreCase);
if (m_stringLength.Success) sb.Add($"StringLength = {m_stringLength.Groups[1].Value}");
else sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
break;
}
break;
case DataType.Dameng:
case DataType.OdbcDameng:
switch (col.DbTypeTextFull.ToLower())
{
case "text": sb.Add("StringLength = -2"); break;
default:
var m_stringLength = Regex.Match(col.DbTypeTextFull, @"^nvarchar2\s*\((\w+)\)$", RegexOptions.IgnoreCase);
if (m_stringLength.Success) sb.Add($"StringLength = {m_stringLength.Groups[1].Value}");
else sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
break;
}
break;
case DataType.Sqlite:
switch (col.DbTypeTextFull.ToLower())
{
case "text": sb.Add("StringLength = -2"); break;
default:
var m_stringLength = Regex.Match(col.DbTypeTextFull, @"^nvarchar\s*\((\w+)\)$", RegexOptions.IgnoreCase);
if (m_stringLength.Success) sb.Add($"StringLength = {m_stringLength.Groups[1].Value}");
else sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
break;
}
break;
case DataType.MsAccess:
switch (col.DbTypeTextFull.ToLower())
{
case "longtext": sb.Add("StringLength = -2"); break;
default:
var m_stringLength = Regex.Match(col.DbTypeTextFull, @"^varchar\s*\((\w+)\)$", RegexOptions.IgnoreCase);
if (m_stringLength.Success) sb.Add($"StringLength = {m_stringLength.Groups[1].Value}");
else sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
break;
}
break;
}
#endregion
}
if (col.IsPrimary)
sb.Add("IsPrimary = true");
if (col.IsIdentity)
sb.Add("IsIdentity = true");
if (dbinfo != null && dbinfo.isnullable != col.IsNullable)
{
var cstype = fsql.DbFirst.GetCsType(col);
if (col.IsNullable && cstype.Contains("?") == false && col.CsType.IsValueType)
sb.Add("IsNullable = true");
if (col.IsNullable == false && (cstype.Contains("?") == true || cstype == "string"))
sb.Add("IsNullable = false");
}
if (isInsertValueSql)
{
var defval = GetColumnDefaultValue(col, false);
if (defval == null) //c#默认属性值,就不需要设置 InsertValueSql 了
{
defval = GetColumnDefaultValue(col, true);
if (defval != null)
{
sb.Add("InsertValueSql = \"" + defval.Replace("\"", "\\\"") + "\"");
//sb.Add("CanInsert = false");
}
}
//else
//sb.Add("CanInsert = false");
}
}
if (sb.Any() == false) return null;
return "[Column(" + string.Join(", ", sb) + ")]";
}
public string GetColumnDefaultValue(DbColumnInfo col, bool isInsertValueSql)
{
var defval = col.DefaultValue?.Trim();
if (string.IsNullOrEmpty(defval)) return null;
var cstype = col.CsType.NullableTypeOrThis();
if (fsql.Ado.DataType == DataType.SqlServer || fsql.Ado.DataType == DataType.OdbcSqlServer)
{
if (defval.StartsWith("((") && defval.EndsWith("))")) defval = defval.Substring(2, defval.Length - 4);
else if (defval.StartsWith("('") && defval.EndsWith("')")) defval = defval.Substring(2, defval.Length - 4).Replace("''", "'");
else if (defval.StartsWith("(") && defval.EndsWith(")")) defval = defval.Substring(1, defval.Length - 2);
else return null;
if (defval.StartsWith("N'") && defval.EndsWith("'")) defval = defval.Substring(1);
if (cstype == typeof(Guid) && string.Compare(defval, "newid()", true) == 0) return $"Guid.NewGuid()";
if (cstype == typeof(string) && string.Compare(defval, "newid()", true) == 0) return $"Guid.NewGuid().ToString().ToUpper()";
if (defval == "NULL") return null;
}
if ((cstype == typeof(string) && defval.StartsWith("'") && defval.EndsWith("'::character varying") ||
cstype == typeof(Guid) && defval.StartsWith("'") && defval.EndsWith("'::uuid")
) && (fsql.Ado.DataType == DataType.PostgreSQL || fsql.Ado.DataType == DataType.OdbcPostgreSQL ||
fsql.Ado.DataType == DataType.KingbaseES || fsql.Ado.DataType == DataType.OdbcKingbaseES ||
fsql.Ado.DataType == DataType.ShenTong))
{
defval = defval.Substring(1, defval.LastIndexOf("'::") - 1).Replace("''", "'");
}
else if (defval.StartsWith("'") && defval.EndsWith("'"))
{
defval = defval.Substring(1, defval.Length - 2).Replace("''", "'");
if (fsql.Ado.DataType == DataType.MySql || fsql.Ado.DataType == DataType.OdbcMySql) defval = defval.Replace("\\\\", "\\");
}
if (cstype.IsNumberType() && decimal.TryParse(defval, out var trydec))
{
if (isInsertValueSql) return defval;
if (cstype == typeof(float)) return defval + "f";
if (cstype == typeof(double)) return defval + "d";
if (cstype == typeof(decimal)) return defval + "M";
return defval;
}
if (cstype == typeof(Guid) && Guid.TryParse(defval, out var tryguid)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"Guid.Parse({LiteralString(defval)})";
if (cstype == typeof(DateTime) && DateTime.TryParse(defval, out var trydt)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"DateTime.Parse({LiteralString(defval)})";
if (cstype == typeof(TimeSpan) && TimeSpan.TryParse(defval, out var tryts)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : $"TimeSpan.Parse({LiteralString(defval)})";
if (cstype == typeof(string)) return isInsertValueSql ? (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval) : LiteralString(defval);
if (cstype == typeof(bool)) return isInsertValueSql ? defval : (defval == "1" || defval == "t" ? "true" : "false");
if (fsql.Ado.DataType == DataType.MySql || fsql.Ado.DataType == DataType.OdbcMySql)
if (col.DbType == (int)MySqlDbType.Enum || col.DbType == (int)MySqlDbType.Set)
if (isInsertValueSql) return (fsql.Select<TestTb>() as Select0Provider)._commonUtils.FormatSql("{0}", defval);
return isInsertValueSql ? defval : null; //sql function or exp
}
#endregion
#region mysql enum/set
public string GetMySqlEnumSetDefine()
{
if (fsql.Ado.DataType != FreeSql.DataType.MySql && fsql.Ado.DataType != FreeSql.DataType.OdbcMySql) return null;
var sb = new StringBuilder();
foreach (var col in table.Columns)
{
if (col.DbType == (int)MySqlDbType.Enum || col.DbType == (int)MySqlDbType.Set)
{
if (col.DbType == (int)MySqlDbType.Set) sb.Append("\r\n\t[Flags]");
sb.Append($"\r\n\tpublic enum {this.GetCsName(this.FullTableName)}{this.GetCsName(col.Name).ToUpper()}");
if (col.DbType == (int)MySqlDbType.Set) sb.Append(" : long");
sb.Append(" {\r\n\t\t");
string slkdgjlksdjg = "";
int field_idx = 0;
int unknow_idx = 0;
string exp2 = string.Concat(col.DbTypeTextFull);
int quote_pos = -1;
while (true)
{
int first_pos = quote_pos = exp2.IndexOf('\'', quote_pos + 1);
if (quote_pos == -1) break;
while (true)
{
quote_pos = exp2.IndexOf('\'', quote_pos + 1);
if (quote_pos == -1) break;
int r_cout = 0;
//for (int p = 1; true; p++) {
// if (exp2[quote_pos - p] == '\\') r_cout++;
// else break;
//}
while (exp2[++quote_pos] == '\'') r_cout++;
if (r_cout % 2 == 0/* && quote_pos - first_pos > 2*/)
{
string str2 = exp2.Substring(first_pos + 1, quote_pos - first_pos - 2).Replace("''", "'");
if (Regex.IsMatch(str2, @"^[\u0391-\uFFE5a-zA-Z_\$][\u0391-\uFFE5a-zA-Z_\$\d]*$"))
slkdgjlksdjg += ", " + str2;
else
slkdgjlksdjg += string.Format(@",
/// <summary>
/// {0}
/// </summary>
[Description(""{0}"")]
Unknow{1}", str2.Replace("\"", "\\\""), ++unknow_idx);
if (col.DbType == (int)MySqlDbType.Set)
slkdgjlksdjg += " = " + Math.Pow(2, field_idx++);
if (col.DbType == (int)MySqlDbType.Enum && field_idx++ == 0)
slkdgjlksdjg += " = 1";
break;
}
}
if (quote_pos == -1) break;
}
sb.Append(slkdgjlksdjg.Substring(2).TrimStart('\r', '\n', '\t'));
sb.Append("\r\n\t}");
}
}
return sb.ToString();
}
#endregion
}
[Table(DisableSyncStructure = true)]
class TestTb { public Guid id { get; set; } }