mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 02:32:50 +08:00
- 增加 FreeSql.Generator 实体类生成工具
This commit is contained in:
parent
3a889504fb
commit
7797edebf1
234
Extensions/FreeSql.Generator/ConsoleApp.cs
Normal file
234
Extensions/FreeSql.Generator/ConsoleApp.cs
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
using RazorEngine.Templating;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
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 ArgsFileName { get; }
|
||||||
|
string ArgsOutput { get; }
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
ArgsOutput = Directory.GetCurrentDirectory();
|
||||||
|
ArgsFileName = "{name}.cs";
|
||||||
|
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"" * 自定义模板文件
|
||||||
|
|
||||||
|
-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=192.168.164.10;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},Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789;Max pool size=2""
|
||||||
|
{10} 是国产达梦数据库,需要使用 ODBC 连接
|
||||||
|
|
||||||
|
-FileName 文件名,默认:{name}.cs
|
||||||
|
|
||||||
|
-Output 保存路径,默认为当前 shell 所在目录
|
||||||
|
{11}
|
||||||
|
|
||||||
|
", 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("OdbcDameng", Color.Yellow),
|
||||||
|
new Colorful.Formatter("推荐在实体类目录创建 gen.bat,双击它重新所有实体类", Color.ForestGreen)
|
||||||
|
);
|
||||||
|
wait.Set();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int a = 0; a < args.Length; a++)
|
||||||
|
{
|
||||||
|
switch (args[a])
|
||||||
|
{
|
||||||
|
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]); break;
|
||||||
|
}
|
||||||
|
a++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-NameOptions":
|
||||||
|
ArgsNameOptions = args[a + 1].Split(',').Select(opt => opt == "1").ToArray();
|
||||||
|
if (ArgsNameOptions.Length != 4) throw new ArgumentException("-NameOptions 参数错误,格式为:0,0,0,0");
|
||||||
|
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("-DB 参数错误,格式为:MySql,ConnectionString");
|
||||||
|
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 "odbcdameng": ArgsDbType = DataType.OdbcDameng; break;
|
||||||
|
default: throw new ArgumentException($"-DB 参数错误,不支持的类型:{dbargs[0]}");
|
||||||
|
}
|
||||||
|
ArgsConnectionString = dbargs[1].Trim();
|
||||||
|
if (string.IsNullOrEmpty(ArgsConnectionString)) throw new ArgumentException($"-DB 参数错误,未提供 ConnectionString");
|
||||||
|
a++;
|
||||||
|
break;
|
||||||
|
case "-FileName":
|
||||||
|
ArgsFileName = args[a + 1];
|
||||||
|
a++;
|
||||||
|
break;
|
||||||
|
case "-Output":
|
||||||
|
ArgsOutput = args[a + 1];
|
||||||
|
a++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgsOutput = ArgsOutput.Trim().TrimEnd('/', '\\');
|
||||||
|
ArgsOutput += ArgsOutput.Contains("\\") ? "\\" : "/";
|
||||||
|
if (!Directory.Exists(ArgsOutput))
|
||||||
|
Directory.CreateDirectory(ArgsOutput);
|
||||||
|
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
var tables = fsql.DbFirst.GetTablesByDatabase();
|
||||||
|
var outputTables = tables;
|
||||||
|
|
||||||
|
|
||||||
|
//开始生成操作
|
||||||
|
foreach (var table in outputTables)
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
Console.WriteFormatted(" OUT -> " + outputFile + "\r\n", Color.DeepSkyBlue);
|
||||||
|
++outputCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rebuildBat = ArgsOutput + "__重新生成.bat";
|
||||||
|
if (File.Exists(rebuildBat) == false)
|
||||||
|
{
|
||||||
|
File.WriteAllText(rebuildBat, @$"
|
||||||
|
FreeSql.Generator -Razor {ArgsRazorRaw} - NameOptions {string.Join(",", ArgsNameOptions.Select(a => a ? 1 : 0))} -NameSpace {ArgsNameSpace} -DB ""{ArgsDbType},{ArgsConnectionString}""
|
||||||
|
");
|
||||||
|
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);
|
||||||
|
|
||||||
|
Console.ReadKey();
|
||||||
|
wait.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
33
Extensions/FreeSql.Generator/FreeSql.Generator.csproj
Normal file
33
Extensions/FreeSql.Generator/FreeSql.Generator.csproj
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
<PackAsTool>true</PackAsTool>
|
||||||
|
<Authors>2881099</Authors>
|
||||||
|
<Company>2881099</Company>
|
||||||
|
<Product>FreeSql123</Product>
|
||||||
|
<Description>使用 FreeSql 快速生成数据库的实体类; dotnet tool install -g FreeSql.Generator</Description>
|
||||||
|
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
|
||||||
|
<Version>0.12.16</Version>
|
||||||
|
<PackageTags>FreeSql DbFirst 实体生成器</PackageTags>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Colorful.Console" Version="1.2.9" />
|
||||||
|
<PackageReference Include="RazorEngine.NetCore" Version="2.2.4" />
|
||||||
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Odbc\FreeSql.Provider.Odbc.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.SqlServer\FreeSql.Provider.SqlServer.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
22
Extensions/FreeSql.Generator/Program.cs
Normal file
22
Extensions/FreeSql.Generator/Program.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
246
Extensions/FreeSql.Generator/RazorContentManager.cs
Normal file
246
Extensions/FreeSql.Generator/RazorContentManager.cs
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
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 null;
|
||||||
|
return string.Concat("", "", attr.Trim('[', ']'));
|
||||||
|
};
|
||||||
|
Func<DbColumnInfo, string> GetDefaultValue = col => {
|
||||||
|
if (col.CsType == typeof(string)) return "" = string.Empty;"";
|
||||||
|
return """";
|
||||||
|
};
|
||||||
|
}@{
|
||||||
|
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.Coment) == false) {
|
||||||
|
@:/// <summary>
|
||||||
|
@:/// @col.Coment.Replace(""\r\n"", ""\n"").Replace(""\n"", ""\r\n /// "")
|
||||||
|
@:/// </summary>
|
||||||
|
}
|
||||||
|
@:@(""[JsonProperty"" + GetAttributeString(gen.GetColumnAttribute(col)) + ""]"")
|
||||||
|
@:public @gen.GetCsType(col) @gen.GetCsName(col.Name) { get; set; }@GetDefaultValue(col)
|
||||||
|
@:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@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 null;
|
||||||
|
return string.Concat("", "", attr.Trim('[', ']'));
|
||||||
|
};
|
||||||
|
|
||||||
|
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 + ""s"";
|
||||||
|
};
|
||||||
|
}@{
|
||||||
|
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.Coment) == false) {
|
||||||
|
@:/// <summary>
|
||||||
|
@:/// @col.Coment.Replace(""\r\n"", ""\n"").Replace(""\n"", ""\r\n /// "")
|
||||||
|
@:/// </summary>
|
||||||
|
}
|
||||||
|
@:@(""[JsonProperty"" + GetAttributeString(gen.GetColumnAttribute(col)) + ""]"")
|
||||||
|
if (findfks.Any() == false) {
|
||||||
|
@:public @gen.GetCsType(col) @csname { get; set; }
|
||||||
|
} else {
|
||||||
|
@:public @gen.GetCsType(col) @csname { get => _@csname; set {
|
||||||
|
@:if (_@csname == value) return;
|
||||||
|
@:_@csname = value;
|
||||||
|
foreach (var fkcok2 in findfks) {
|
||||||
|
@:@GetFkObjectName(fkcok2) = null;
|
||||||
|
}
|
||||||
|
@:} }
|
||||||
|
@:private @gen.GetCsType(col) _@csname;
|
||||||
|
}
|
||||||
|
@:
|
||||||
|
}
|
||||||
|
@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) @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)> @GetFkObjectNameOutside(fk)s { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@:
|
||||||
|
@:#endregion
|
||||||
|
}
|
||||||
|
@if (isManyToMany) {
|
||||||
|
@:
|
||||||
|
@:#region 外键 => 导航属性,ManyToMany
|
||||||
|
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 csname = rightft.Name;
|
||||||
|
@:
|
||||||
|
@:public@(isLazying ? "" virtual"" : """") List<@gen.GetCsName(fkTableName)> @gen.GetCsName(csname)s { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@:
|
||||||
|
@:#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@gen.GetMySqlEnumSetDefine()
|
||||||
|
}";
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
145
Extensions/FreeSql.Generator/RazorModel.cs
Normal file
145
Extensions/FreeSql.Generator/RazorModel.cs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
using FreeSql.DatabaseModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetCsType(DbColumnInfo col) {
|
||||||
|
if (fsql.Ado.DataType == FreeSql.DataType.MySql)
|
||||||
|
if (col.DbType == (int)MySql.Data.MySqlClient.MySqlDbType.Enum || col.DbType == (int)MySql.Data.MySqlClient.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)
|
||||||
|
sb.Add("Name = \"" + this.FullTableName + "\"");
|
||||||
|
|
||||||
|
if (sb.Any() == false) return null;
|
||||||
|
return "[Table(" + string.Join(", ", sb) + ")]";
|
||||||
|
}
|
||||||
|
public string GetColumnAttribute(DbColumnInfo col) {
|
||||||
|
var sb = new List<string>();
|
||||||
|
|
||||||
|
if (GetCsName(col.Name) != col.Name)
|
||||||
|
sb.Add("Name = \"" + col.Name + "\"");
|
||||||
|
|
||||||
|
var dbinfo = fsql.CodeFirst.GetDbInfo(col.CsType);
|
||||||
|
if (dbinfo != null && dbinfo.Value.dbtypeFull.Replace("NOT NULL", "").Trim() != col.DbTypeTextFull)
|
||||||
|
sb.Add("DbType = \"" + col.DbTypeTextFull + "\"");
|
||||||
|
if (col.IsPrimary)
|
||||||
|
sb.Add("IsPrimary = true");
|
||||||
|
if (col.IsIdentity)
|
||||||
|
sb.Add("IsIdentity = true");
|
||||||
|
|
||||||
|
if (dbinfo != null && dbinfo.Value.isnullable != col.IsNullable) {
|
||||||
|
if (col.IsNullable && fsql.DbFirst.GetCsType(col).Contains("?") == false && col.CsType.IsValueType)
|
||||||
|
sb.Add("IsNullable = true");
|
||||||
|
if (col.IsNullable == false && fsql.DbFirst.GetCsType(col).Contains("?") == true)
|
||||||
|
sb.Add("IsNullable = false");
|
||||||
|
}
|
||||||
|
if (sb.Any() == false) return null;
|
||||||
|
return "[Column(" + string.Join(", ", sb) + ")]";
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region mysql enum/set
|
||||||
|
public string GetMySqlEnumSetDefine() {
|
||||||
|
if (fsql.Ado.DataType != FreeSql.DataType.MySql) return null;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var col in table.Columns) {
|
||||||
|
if (col.DbType == (int)MySql.Data.MySqlClient.MySqlDbType.Enum || col.DbType == (int)MySql.Data.MySqlClient.MySqlDbType.Set) {
|
||||||
|
if (col.DbType == (int)MySql.Data.MySqlClient.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)MySql.Data.MySqlClient.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)MySql.Data.MySqlClient.MySqlDbType.Set)
|
||||||
|
slkdgjlksdjg += " = " + Math.Pow(2, field_idx++);
|
||||||
|
if (col.DbType == (int)MySql.Data.MySqlClient.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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
15
FreeSql.sln
15
FreeSql.sln
@ -66,6 +66,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Tests.Provider.Odbc
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "orm_vs_net40", "Examples\orm_vs_net40\orm_vs_net40.csproj", "{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "orm_vs_net40", "Examples\orm_vs_net40\orm_vs_net40.csproj", "{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Generator", "Extensions\FreeSql.Generator\FreeSql.Generator.csproj", "{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -388,6 +390,18 @@ Global
|
|||||||
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}.Release|x64.Build.0 = Release|Any CPU
|
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}.Release|x86.ActiveCfg = Release|Any CPU
|
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}.Release|x86.Build.0 = Release|Any CPU
|
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -411,6 +425,7 @@ Global
|
|||||||
{3043DEF1-85DF-47AD-8D5D-327270794356} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
{3043DEF1-85DF-47AD-8D5D-327270794356} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
||||||
{C57444BA-8BF7-4790-A864-7F237123219B} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
|
{C57444BA-8BF7-4790-A864-7F237123219B} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
|
||||||
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
|
{1674BCE3-EEB4-4003-A2A7-06F51EFAEA23} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
|
||||||
|
{6A3A4470-7DF7-411B-AAD7-755D7A9DB5A4} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98}
|
SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98}
|
||||||
|
@ -9,7 +9,7 @@ FreeSql 是功能强大的对象关系映射技术(O/RM),支持 .NETCore 2.1+
|
|||||||
# Features
|
# Features
|
||||||
|
|
||||||
- [x] 支持 CodeFirst 迁移;
|
- [x] 支持 CodeFirst 迁移;
|
||||||
- [x] 支持 DbFirst 从数据库导入实体类;
|
- [x] 支持 DbFirst 从数据库导入实体类,[安装实体类生成工具](https://github.com/2881099/FreeSql/wiki/DbFirst);
|
||||||
- [x] 大量采用 ExpressionTree 提升性能;
|
- [x] 大量采用 ExpressionTree 提升性能;
|
||||||
- [x] 支持 深入的类型映射,比如pgsql的数组类型;
|
- [x] 支持 深入的类型映射,比如pgsql的数组类型;
|
||||||
- [x] 支持 丰富的表达式函数;
|
- [x] 支持 丰富的表达式函数;
|
||||||
@ -43,12 +43,6 @@ FreeSql 是功能强大的对象关系映射技术(O/RM),支持 .NETCore 2.1+
|
|||||||
- 要么[FreeSql.Connection.Extensions](https://github.com/2881099/FreeSql.Connection.Extensions),有点像Dapper的使用习惯;
|
- 要么[FreeSql.Connection.Extensions](https://github.com/2881099/FreeSql.Connection.Extensions),有点像Dapper的使用习惯;
|
||||||
- 要么[BaseEntity](https://github.com/2881099/FreeSql/tree/master/Examples/base_entity),我求简单现在使用的这个;
|
- 要么[BaseEntity](https://github.com/2881099/FreeSql/tree/master/Examples/base_entity),我求简单现在使用的这个;
|
||||||
|
|
||||||
> 其他下载
|
|
||||||
|
|
||||||
- [FreeSql.Tools 生成器](https://github.com/2881099/FreeSql.Tools),基于 razor 模板的生成器;
|
|
||||||
- [Abp 中使用 FreeSql](https://github.com/gnsilence/JPGZService),测试中...;
|
|
||||||
- [FreeSql 优势.pptx](https://github.com/2881099/FreeSql/files/3305852/FreeSql.pptx);
|
|
||||||
|
|
||||||
> 学习项目
|
> 学习项目
|
||||||
|
|
||||||
- [😃 A simple and practical CMS implememted by .NET Core 2.2](https://github.com/luoyunchong/lin-cms-dotnetcore)
|
- [😃 A simple and practical CMS implememted by .NET Core 2.2](https://github.com/luoyunchong/lin-cms-dotnetcore)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user