diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0579872 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*.cs] +charset = utf-8 #设置文件字符集为utf-8,在 Linux 系统中,通常推荐使用 UTF-8 而不是 UTF-8 with BOM。添加 BOM 可能会干扰那些不期望在文件开头出现非 ASCII 字节的软件对 UTF-8 的使用。 diff --git a/HuanMengProject.sln b/HuanMengProject.sln index 1ca6d3d..ffaada8 100644 --- a/HuanMengProject.sln +++ b/HuanMengProject.sln @@ -31,7 +31,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HuanMeng.StableDiffusion.Te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextGenerationApi", "src\2-api\TextGenerationApi\TextGenerationApi.csproj", "{A9C5939E-D239-4AB8-9380-7E76166326D9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HuanMnegopneaiTest", "src\5-console\HuanMnegopneaiTest\HuanMnegopneaiTest.csproj", "{D2A74CFA-8A03-4272-89C7-C01830D183F1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HuanMnegopneaiTest", "src\5-console\HuanMnegopneaiTest\HuanMnegopneaiTest.csproj", "{D2A74CFA-8A03-4272-89C7-C01830D183F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HuanMeng.MiaoYu.Model", "src\0-core\HuanMeng.MiaoYu.Model\HuanMeng.MiaoYu.Model.csproj", "{B845C884-AD1A-4483-A2F6-B218DB14EA2D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6C59E75C-386D-4325-9752-D7DB8B158BF8}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -67,6 +74,10 @@ Global {D2A74CFA-8A03-4272-89C7-C01830D183F1}.Debug|Any CPU.Build.0 = Debug|Any CPU {D2A74CFA-8A03-4272-89C7-C01830D183F1}.Release|Any CPU.ActiveCfg = Release|Any CPU {D2A74CFA-8A03-4272-89C7-C01830D183F1}.Release|Any CPU.Build.0 = Release|Any CPU + {B845C884-AD1A-4483-A2F6-B218DB14EA2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B845C884-AD1A-4483-A2F6-B218DB14EA2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B845C884-AD1A-4483-A2F6-B218DB14EA2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B845C884-AD1A-4483-A2F6-B218DB14EA2D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -86,6 +97,7 @@ Global {054AFFF5-D25E-4EC7-A135-050EEE7F7FA0} = {8D39E84B-2810-41D7-AFE6-0A58E09E34C3} {A9C5939E-D239-4AB8-9380-7E76166326D9} = {0C0B6EB5-E41D-46D9-9F60-90D320A2EEF3} {D2A74CFA-8A03-4272-89C7-C01830D183F1} = {F34C5BC4-8810-4D6A-B003-AFE12D7ED4BA} + {B845C884-AD1A-4483-A2F6-B218DB14EA2D} = {DD14191F-22CE-48D8-A944-B8A41C97ACD4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4A1DC406-AFAA-4884-859C-51B9B26E37FC} diff --git a/src/0-core/HuanMeng.DotNetCore/Base/BaseResponse.cs b/src/0-core/HuanMeng.DotNetCore/Base/BaseResponse.cs index 972f554..b75da7a 100644 --- a/src/0-core/HuanMeng.DotNetCore/Base/BaseResponse.cs +++ b/src/0-core/HuanMeng.DotNetCore/Base/BaseResponse.cs @@ -13,6 +13,7 @@ namespace HuanMeng.DotNetCore.Base [Serializable] public class BaseResponse : IResponse { + ///// ///// Http鐘舵佺爜 ///// @@ -54,6 +55,7 @@ namespace HuanMeng.DotNetCore.Base Code = code; Message = message; Data = default(T); + } diff --git a/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj b/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj index 372b737..4cd9dad 100644 --- a/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj +++ b/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj @@ -8,6 +8,7 @@ + diff --git a/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenant.cs b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenant.cs new file mode 100644 index 0000000..a8a5b62 --- /dev/null +++ b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenant.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.MultiTenant.Contract +{ + /// + /// 鍩烘湰澶氱鎴锋帴鍙 + /// + public interface IMultiTenant + { + /// + /// 绉熸埛ID + /// + Guid TenantId { get; set; } + } +} diff --git a/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenantDbContext.cs b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenantDbContext.cs new file mode 100644 index 0000000..21b2ec2 --- /dev/null +++ b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenantDbContext.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.MultiTenant.Contract +{ + /// + /// 澶氱鎴稤bContent鎺ュ彛 + /// + public interface IMultiTenantDbContext + { + /// + /// 绉熸埛淇℃伅 + /// + ITenantInfo TenantInfo { get; } + } +} diff --git a/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenantEntity.cs b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenantEntity.cs new file mode 100644 index 0000000..7ab6888 --- /dev/null +++ b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/IMultiTenantEntity.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.MultiTenant.Contract +{ + /// + /// 澶氱鎴峰疄浣撶被鎺ュ彛 + /// + public interface IMultiTenantEntity : IMultiTenant + { + } +} diff --git a/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/ITenantInfo.cs b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/ITenantInfo.cs new file mode 100644 index 0000000..2fe50e6 --- /dev/null +++ b/src/0-core/HuanMeng.DotNetCore/MultiTenant/Contract/ITenantInfo.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.MultiTenant.Contract +{ + + /// + /// 绉熸埛淇℃伅鎺ュ彛 + /// + public interface ITenantInfo : IMultiTenant + { + + string? Identifier { get; set; } + + /// + /// Gets or sets a display friendly name for the tenant. + /// + string? Name { get; set; } + + /// + /// 鏁版嵁搴撹繛鎺ュ瓧绗︿覆 + /// + string? ConnectionString { get; set; } + } +} diff --git a/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantDbContext.cs b/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantDbContext.cs new file mode 100644 index 0000000..d8adb2c --- /dev/null +++ b/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantDbContext.cs @@ -0,0 +1,49 @@ +using HuanMeng.DotNetCore.MultiTenant.Contract; + +using Microsoft.EntityFrameworkCore; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.MultiTenant +{ + /// + /// 鍩烘湰澶氱鎴稤bContext + /// + public class MultiTenantDbContext : DbContext, IMultiTenantDbContext + { + /// + /// 绉熸埛淇℃伅 + /// + public ITenantInfo TenantInfo { get; set; } + + + /// + /// 鏋勯犲嚱鏁 + /// + /// + public MultiTenantDbContext(ITenantInfo tenantInfo) + { + this.TenantInfo = tenantInfo; + } + + /// + /// 鏋勯犲嚱鏁 + /// + /// + /// + public MultiTenantDbContext(ITenantInfo tenantInfo, DbContextOptions options) + : base(options) + { + this.TenantInfo = tenantInfo; + } + + public void SetTenantInfo(ITenantInfo tenantInfo) + { + this.TenantInfo = tenantInfo; + } + } +} diff --git a/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantEntity.cs b/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantEntity.cs new file mode 100644 index 0000000..ddd5e36 --- /dev/null +++ b/src/0-core/HuanMeng.DotNetCore/MultiTenant/MultiTenantEntity.cs @@ -0,0 +1,22 @@ +using HuanMeng.DotNetCore.MultiTenant.Contract; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HuanMeng.DotNetCore.MultiTenant +{ + /// + /// 鍩烘湰澶氱鎴峰疄浣撶被 + /// + public class MultiTenantEntity : IMultiTenantEntity + { + /// + /// 绉熸埛ID + /// + public Guid TenantId { get; set; } + + } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/CodeTemplates/EFCore/DbContext.t4 b/src/0-core/HuanMeng.MiaoYu.Model/CodeTemplates/EFCore/DbContext.t4 new file mode 100644 index 0000000..781fe74 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/CodeTemplates/EFCore/DbContext.t4 @@ -0,0 +1,386 @@ +<#@ template hostSpecific="true" #> +<#@ assembly name="Microsoft.EntityFrameworkCore" #> +<#@ assembly name="Microsoft.EntityFrameworkCore.Design" #> +<#@ assembly name="Microsoft.EntityFrameworkCore.Relational" #> +<#@ assembly name="Microsoft.Extensions.DependencyInjection.Abstractions" #> +<#@ parameter name="Model" type="Microsoft.EntityFrameworkCore.Metadata.IModel" #> +<#@ parameter name="Options" type="Microsoft.EntityFrameworkCore.Scaffolding.ModelCodeGenerationOptions" #> +<#@ parameter name="NamespaceHint" type="System.String" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="Microsoft.EntityFrameworkCore" #> +<#@ import namespace="Microsoft.EntityFrameworkCore.Design" #> +<#@ import namespace="Microsoft.EntityFrameworkCore.Infrastructure" #> +<#@ import namespace="Microsoft.EntityFrameworkCore.Scaffolding" #> +<#@ import namespace="Microsoft.Extensions.DependencyInjection" #> +<# + if (!ProductInfo.GetVersion().StartsWith("8.0")) + { + Warning("Your templates were created using an older version of Entity Framework. Additional features and bug fixes may be available. See https://aka.ms/efcore-docs-updating-templates for more information."); + } + + var services = (IServiceProvider)Host; + var providerCode = services.GetRequiredService(); + var annotationCodeGenerator = services.GetRequiredService(); + var code = services.GetRequiredService(); + + var usings = new List + { + "System", + "System.Collections.Generic", + "Microsoft.EntityFrameworkCore" + }; + + if (NamespaceHint != Options.ModelNamespace + && !string.IsNullOrEmpty(Options.ModelNamespace)) + { + usings.Add(Options.ModelNamespace); + } + + if (!string.IsNullOrEmpty(NamespaceHint)) + { +#> +namespace <#= NamespaceHint #>; + +<# + } +#> +/// +/// 妙语实体类 +/// +public partial class <#= Options.ContextName #> : MultiTenantDbContext//DbContext +{ +<# + if (!Options.SuppressOnConfiguring) + { +#> + public <#= Options.ContextName #>() : base(null) + { + } + +<# + } +#> + public <#= Options.ContextName #>(DbContextOptions<<#= Options.ContextName #>> options) + : base(null, options) + { + } + + /// + /// + /// + /// + public <#= Options.ContextName #>(ITenantInfo tenantInfo) : base(tenantInfo) + { + + } + + + /// + /// + /// + /// + /// + public <#= Options.ContextName #>(ITenantInfo tenantInfo, DbContextOptions<<#= Options.ContextName #>> options) : base(tenantInfo, options) + { + } + + +<# + foreach (var entityType in Model.GetEntityTypes().Where(e => !e.IsSimpleManyToManyJoinEntityType())) + { +#> + /// + /// <#=entityType.GetComment()??"" #> + /// + public virtual DbSet<<#= entityType.Name #>> <#= entityType.GetDbSetName() #> { get; set; } + +<# + } + + if (!Options.SuppressOnConfiguring) + { +#> + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) +<# + if (!Options.SuppressConnectionStringWarning) + { +#> +//#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263. +<# + } + + var useProviderCall = providerCode.GenerateUseProvider(Options.ConnectionString); + usings.AddRange(useProviderCall.GetRequiredUsings()); +#> + => optionsBuilder<#= code.Fragment(useProviderCall, indent: 3) #>; + +<# + } + +#> + protected override void OnModelCreating(ModelBuilder modelBuilder) + { +<# + var anyConfiguration = false; + + var modelFluentApiCalls = Model.GetFluentApiCalls(annotationCodeGenerator); + if (modelFluentApiCalls != null) + { + usings.AddRange(modelFluentApiCalls.GetRequiredUsings()); +#> + modelBuilder<#= code.Fragment(modelFluentApiCalls, indent: 3) #>; +<# + anyConfiguration = true; + } + + StringBuilder mainEnvironment; + foreach (var entityType in Model.GetEntityTypes().Where(e => !e.IsSimpleManyToManyJoinEntityType())) + { + // Save all previously generated code, and start generating into a new temporary environment + mainEnvironment = GenerationEnvironment; + GenerationEnvironment = new StringBuilder(); + + if (anyConfiguration) + { + WriteLine(""); + } + + var anyEntityTypeConfiguration = false; +#> + modelBuilder.Entity<<#= entityType.Name #>>(entity => + { +<# + var key = entityType.FindPrimaryKey(); + if (key != null) + { + var keyFluentApiCalls = key.GetFluentApiCalls(annotationCodeGenerator); + if (keyFluentApiCalls != null + || (!key.IsHandledByConvention() && !Options.UseDataAnnotations)) + { + if (keyFluentApiCalls != null) + { + usings.AddRange(keyFluentApiCalls.GetRequiredUsings()); + } +#> + entity.HasKey(<#= code.Lambda(key.Properties, "e") #>)<#= code.Fragment(keyFluentApiCalls, indent: 4) #>; +<# + anyEntityTypeConfiguration = true; + } + } + + var entityTypeFluentApiCalls = entityType.GetFluentApiCalls(annotationCodeGenerator) + ?.FilterChain(c => !(Options.UseDataAnnotations && c.IsHandledByDataAnnotations)); + if (entityTypeFluentApiCalls != null) + { + usings.AddRange(entityTypeFluentApiCalls.GetRequiredUsings()); + + if (anyEntityTypeConfiguration) + { + WriteLine(""); + } +#> + entity<#= code.Fragment(entityTypeFluentApiCalls, indent: 4) #>; +<# + anyEntityTypeConfiguration = true; + } + + foreach (var index in entityType.GetIndexes() + .Where(i => !(Options.UseDataAnnotations && i.IsHandledByDataAnnotations(annotationCodeGenerator)))) + { + if (anyEntityTypeConfiguration) + { + WriteLine(""); + } + + var indexFluentApiCalls = index.GetFluentApiCalls(annotationCodeGenerator); + if (indexFluentApiCalls != null) + { + usings.AddRange(indexFluentApiCalls.GetRequiredUsings()); + } +#> + entity.HasIndex(<#= code.Lambda(index.Properties, "e") #>, <#= code.Literal(index.GetDatabaseName()) #>)<#= code.Fragment(indexFluentApiCalls, indent: 4) #>; +<# + anyEntityTypeConfiguration = true; + } + + var firstProperty = true; + foreach (var property in entityType.GetProperties()) + { + var propertyFluentApiCalls = property.GetFluentApiCalls(annotationCodeGenerator) + ?.FilterChain(c => !(Options.UseDataAnnotations && c.IsHandledByDataAnnotations) + && !(c.Method == "IsRequired" && Options.UseNullableReferenceTypes && !property.ClrType.IsValueType)); + if (propertyFluentApiCalls == null) + { + continue; + } + + usings.AddRange(propertyFluentApiCalls.GetRequiredUsings()); + + if (anyEntityTypeConfiguration && firstProperty) + { + WriteLine(""); + } +#> + entity.Property(e => e.<#= property.Name #>)<#= code.Fragment(propertyFluentApiCalls, indent: 4) #>; +<# + anyEntityTypeConfiguration = true; + firstProperty = false; + } + + foreach (var foreignKey in entityType.GetForeignKeys()) + { + var foreignKeyFluentApiCalls = foreignKey.GetFluentApiCalls(annotationCodeGenerator) + ?.FilterChain(c => !(Options.UseDataAnnotations && c.IsHandledByDataAnnotations)); + if (foreignKeyFluentApiCalls == null) + { + continue; + } + + usings.AddRange(foreignKeyFluentApiCalls.GetRequiredUsings()); + + if (anyEntityTypeConfiguration) + { + WriteLine(""); + } +#> + entity.HasOne(d => d.<#= foreignKey.DependentToPrincipal.Name #>).<#= foreignKey.IsUnique ? "WithOne" : "WithMany" #>(<#= foreignKey.PrincipalToDependent != null ? $"p => p.{foreignKey.PrincipalToDependent.Name}" : "" #>)<#= code.Fragment(foreignKeyFluentApiCalls, indent: 4) #>; +<# + anyEntityTypeConfiguration = true; + } + + foreach (var skipNavigation in entityType.GetSkipNavigations().Where(n => n.IsLeftNavigation())) + { + if (anyEntityTypeConfiguration) + { + WriteLine(""); + } + + var left = skipNavigation.ForeignKey; + var leftFluentApiCalls = left.GetFluentApiCalls(annotationCodeGenerator, useStrings: true); + var right = skipNavigation.Inverse.ForeignKey; + var rightFluentApiCalls = right.GetFluentApiCalls(annotationCodeGenerator, useStrings: true); + var joinEntityType = skipNavigation.JoinEntityType; + + if (leftFluentApiCalls != null) + { + usings.AddRange(leftFluentApiCalls.GetRequiredUsings()); + } + + if (rightFluentApiCalls != null) + { + usings.AddRange(rightFluentApiCalls.GetRequiredUsings()); + } +#> + entity.HasMany(d => d.<#= skipNavigation.Name #>).WithMany(p => p.<#= skipNavigation.Inverse.Name #>) + .UsingEntity>( + <#= code.Literal(joinEntityType.Name) #>, + r => r.HasOne<<#= right.PrincipalEntityType.Name #>>().WithMany()<#= code.Fragment(rightFluentApiCalls, indent: 6) #>, + l => l.HasOne<<#= left.PrincipalEntityType.Name #>>().WithMany()<#= code.Fragment(leftFluentApiCalls, indent: 6) #>, + j => + { +<# + var joinKey = joinEntityType.FindPrimaryKey(); + var joinKeyFluentApiCalls = joinKey.GetFluentApiCalls(annotationCodeGenerator); + + if (joinKeyFluentApiCalls != null) + { + usings.AddRange(joinKeyFluentApiCalls.GetRequiredUsings()); + } +#> + j.HasKey(<#= code.Arguments(joinKey.Properties.Select(e => e.Name)) #>)<#= code.Fragment(joinKeyFluentApiCalls, indent: 7) #>; +<# + var joinEntityTypeFluentApiCalls = joinEntityType.GetFluentApiCalls(annotationCodeGenerator); + if (joinEntityTypeFluentApiCalls != null) + { + usings.AddRange(joinEntityTypeFluentApiCalls.GetRequiredUsings()); +#> + j<#= code.Fragment(joinEntityTypeFluentApiCalls, indent: 7) #>; +<# + } + + foreach (var index in joinEntityType.GetIndexes()) + { + var indexFluentApiCalls = index.GetFluentApiCalls(annotationCodeGenerator); + if (indexFluentApiCalls != null) + { + usings.AddRange(indexFluentApiCalls.GetRequiredUsings()); + } +#> + j.HasIndex(<#= code.Literal(index.Properties.Select(e => e.Name).ToArray()) #>, <#= code.Literal(index.GetDatabaseName()) #>)<#= code.Fragment(indexFluentApiCalls, indent: 7) #>; +<# + } + + foreach (var property in joinEntityType.GetProperties()) + { + var propertyFluentApiCalls = property.GetFluentApiCalls(annotationCodeGenerator); + if (propertyFluentApiCalls == null) + { + continue; + } + + usings.AddRange(propertyFluentApiCalls.GetRequiredUsings()); +#> + j.IndexerProperty<<#= code.Reference(property.ClrType) #>>(<#= code.Literal(property.Name) #>)<#= code.Fragment(propertyFluentApiCalls, indent: 7) #>; + //添加全局筛选器 + if (this.TenantInfo != null) + { + entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId); + } +<# + } +#> + }); +<# + anyEntityTypeConfiguration = true; + } +#> + }); +<# + // If any signicant code was generated, append it to the main environment + if (anyEntityTypeConfiguration) + { + mainEnvironment.Append(GenerationEnvironment); + anyConfiguration = true; + } + + // Resume generating code into the main environment + GenerationEnvironment = mainEnvironment; + } + + foreach (var sequence in Model.GetSequences()) + { + var needsType = sequence.Type != typeof(long); + var needsSchema = !string.IsNullOrEmpty(sequence.Schema) && sequence.Schema != sequence.Model.GetDefaultSchema(); + var sequenceFluentApiCalls = sequence.GetFluentApiCalls(annotationCodeGenerator); +#> + modelBuilder.HasSequence<#= needsType ? $"<{code.Reference(sequence.Type)}>" : "" #>(<#= code.Literal(sequence.Name) #><#= needsSchema ? $", {code.Literal(sequence.Schema)}" : "" #>)<#= code.Fragment(sequenceFluentApiCalls, indent: 3) #>; +<# + } + + if (anyConfiguration) + { + WriteLine(""); + } +#> + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); +} +<# + mainEnvironment = GenerationEnvironment; + GenerationEnvironment = new StringBuilder(); + + foreach (var ns in usings.Distinct().OrderBy(x => x, new NamespaceComparer())) + { +#> +using <#= ns #>; +<# + } + + WriteLine(""); + + GenerationEnvironment.Append(mainEnvironment); +#> diff --git a/src/0-core/HuanMeng.MiaoYu.Model/CodeTemplates/EFCore/EntityType.t4 b/src/0-core/HuanMeng.MiaoYu.Model/CodeTemplates/EFCore/EntityType.t4 new file mode 100644 index 0000000..95e0191 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/CodeTemplates/EFCore/EntityType.t4 @@ -0,0 +1,177 @@ +<#@ template hostSpecific="true" #> +<#@ assembly name="Microsoft.EntityFrameworkCore" #> +<#@ assembly name="Microsoft.EntityFrameworkCore.Design" #> +<#@ assembly name="Microsoft.EntityFrameworkCore.Relational" #> +<#@ assembly name="Microsoft.Extensions.DependencyInjection.Abstractions" #> +<#@ parameter name="EntityType" type="Microsoft.EntityFrameworkCore.Metadata.IEntityType" #> +<#@ parameter name="Options" type="Microsoft.EntityFrameworkCore.Scaffolding.ModelCodeGenerationOptions" #> +<#@ parameter name="NamespaceHint" type="System.String" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.ComponentModel.DataAnnotations" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="Microsoft.EntityFrameworkCore" #> +<#@ import namespace="Microsoft.EntityFrameworkCore.Design" #> +<#@ import namespace="Microsoft.Extensions.DependencyInjection" #> +<# + if (EntityType.IsSimpleManyToManyJoinEntityType()) + { + // Don't scaffold these + return ""; + } + + var services = (IServiceProvider)Host; + var annotationCodeGenerator = services.GetRequiredService(); + var code = services.GetRequiredService(); + + var usings = new List + { + // "System", + //"System.Collections.Generic", + }; + + if (Options.UseDataAnnotations) + { + usings.Add("System.ComponentModel.DataAnnotations"); + usings.Add("System.ComponentModel.DataAnnotations.Schema"); + usings.Add("Microsoft.EntityFrameworkCore"); + } + + if (!string.IsNullOrEmpty(NamespaceHint)) + { +#> +namespace <#= NamespaceHint #>; + +<# + } + + if (!string.IsNullOrEmpty(EntityType.GetComment())) + { +#> +/// +/// <#= code.XmlComment(EntityType.GetComment()) #> +/// +<# + } + + if (Options.UseDataAnnotations) + { + foreach (var dataAnnotation in EntityType.GetDataAnnotations(annotationCodeGenerator)) + { +#> +<#= code.Fragment(dataAnnotation) #> +<# + } + } +#> +public partial class <#= EntityType.Name #>: MultiTenantEntity +{ +<# + var firstProperty = true; + foreach (var property in EntityType.GetProperties().OrderBy(p => p.GetColumnOrder() ?? -1)) + { + if (!firstProperty) + { + WriteLine(""); + } + + if(property.Name=="TenantId"){ + continue; + } + if (!string.IsNullOrEmpty(property.GetComment())) + { +#> + /// + /// <#= code.XmlComment(property.GetComment(), indent: 1) #> + /// +<# + } + + if (Options.UseDataAnnotations) + { + var dataAnnotations = property.GetDataAnnotations(annotationCodeGenerator) + .Where(a => !(a.Type == typeof(RequiredAttribute) && Options.UseNullableReferenceTypes && !property.ClrType.IsValueType)); + foreach (var dataAnnotation in dataAnnotations) + { +#> + <#= code.Fragment(dataAnnotation) #> +<# + } + } + + usings.AddRange(code.GetRequiredUsings(property.ClrType)); + + var needsNullable = Options.UseNullableReferenceTypes && property.IsNullable && !property.ClrType.IsValueType; + var needsInitializer = Options.UseNullableReferenceTypes && !property.IsNullable && !property.ClrType.IsValueType; + +#> + public <#= code.Reference(property.ClrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #> +<# + firstProperty = false; + } + + foreach (var navigation in EntityType.GetNavigations()) + { + WriteLine(""); + + if (Options.UseDataAnnotations) + { + foreach (var dataAnnotation in navigation.GetDataAnnotations(annotationCodeGenerator)) + { +#> + <#= code.Fragment(dataAnnotation) #> +<# + } + } + + var targetType = navigation.TargetEntityType.Name; + if (navigation.IsCollection) + { +#> + public virtual ICollection<<#= targetType #>> <#= navigation.Name #> { get; set; } = new List<<#= targetType #>>(); +<# + } + else + { + var needsNullable = Options.UseNullableReferenceTypes && !(navigation.ForeignKey.IsRequired && navigation.IsOnDependent); + var needsInitializer = Options.UseNullableReferenceTypes && navigation.ForeignKey.IsRequired && navigation.IsOnDependent; +#> + public virtual <#= targetType #><#= needsNullable ? "?" : "" #> <#= navigation.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #> +<# + } + } + + foreach (var skipNavigation in EntityType.GetSkipNavigations()) + { + WriteLine(""); + + if (Options.UseDataAnnotations) + { + foreach (var dataAnnotation in skipNavigation.GetDataAnnotations(annotationCodeGenerator)) + { +#> + <#= code.Fragment(dataAnnotation) #> +<# + } + } +#> + public virtual ICollection<<#= skipNavigation.TargetEntityType.Name #>> <#= skipNavigation.Name #> { get; set; } = new List<<#= skipNavigation.TargetEntityType.Name #>>(); +<# + } +#> +} +<# + var previousOutput = GenerationEnvironment; + GenerationEnvironment = new StringBuilder(); + + foreach (var ns in usings.Distinct().OrderBy(x => x, new NamespaceComparer())) + { +#> +using <#= ns #>; +<# + } + + WriteLine(""); + + GenerationEnvironment.Append(previousOutput); +#> diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs new file mode 100644 index 0000000..6beebf5 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; + +/// +/// +/// +public partial class MiaoYuContext : MultiTenantDbContext//DbContext +{ + public MiaoYuContext() : base(null) + { + } + + public MiaoYuContext(DbContextOptions options) + : base(null, options) + { + } + + /// + /// + /// + /// + public MiaoYuContext(ITenantInfo tenantInfo) : base(tenantInfo) + { + + } + + + /// + /// + /// + /// + /// + public MiaoYuContext(ITenantInfo tenantInfo, DbContextOptions options) : base(tenantInfo, options) + { + } + + + /// + /// 鐢ㄦ埛琛 + /// + public virtual DbSet T_User { get; set; } + + /// + /// 鐢ㄦ埛淇℃伅琛 + /// + public virtual DbSet T_User_Data { get; set; } + + /// + /// 鎵嬫満鍙风櫥褰曡〃 + /// + public virtual DbSet T_User_Phone_Account { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) +//#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263. + => optionsBuilder.UseSqlServer("Server=192.168.195.2;Database=MiaoYu;User Id=zpc;Password=zpc;TrustServerCertificate=true;"); + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_User__3214EC073733108B"); + + entity.ToTable(tb => tb.HasComment("鐢ㄦ埛琛")); + + entity.Property(e => e.Id).HasComment("鐢ㄦ埛Id"); + entity.Property(e => e.CreatedAt) + .HasComment("鍒涘缓鏃堕棿") + .HasColumnType("datetime"); + entity.Property(e => e.Email) + .HasMaxLength(255) + .HasComment("缁戝畾鐨勯偖绠"); + entity.Property(e => e.IsActive).HasComment("鏄惁娲昏穬"); + entity.Property(e => e.LastLoginAt) + .HasComment("鏈鍚庝竴娆$櫥褰曟椂闂") + .HasColumnType("datetime"); + entity.Property(e => e.LastLoginTypeAt).HasComment("鏈鍚庝竴娆$櫥褰曟柟寮,1鎵嬫満鍙"); + entity.Property(e => e.NickName) + .HasMaxLength(100) + .HasComment("鐢ㄦ埛鏄电О"); + entity.Property(e => e.PhoneNum) + .HasMaxLength(50) + .IsUnicode(false) + .HasComment("缁戝畾鐨勬墜鏈哄彿"); + entity.Property(e => e.RegisterType).HasComment("棣栨娉ㄥ唽鏂瑰紡"); + entity.Property(e => e.TenantId).HasComment("绉熸埛Id"); + entity.Property(e => e.UpdatedAt) + .HasComment("淇敼鏃堕棿") + .HasColumnType("datetime"); + entity.Property(e => e.UserName) + .HasMaxLength(100) + .HasComment("鐢ㄦ埛濮撳悕"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => new { e.Id, e.UserId }).HasName("PK__T_User_D__E36C60C3D959FD89"); + + entity.ToTable(tb => tb.HasComment("鐢ㄦ埛淇℃伅琛")); + + entity.Property(e => e.Id) + .ValueGeneratedOnAdd() + .HasComment("涓婚敭"); + entity.Property(e => e.UserId).HasComment("鐢ㄦ埛Id"); + entity.Property(e => e.CreatedAt_) + .HasComment("鍒涘缓鏃堕棿") + .HasColumnType("datetime") + .HasColumnName("CreatedAt "); + entity.Property(e => e.Currency).HasComment("璐у竵"); + entity.Property(e => e.IP) + .HasMaxLength(25) + .IsUnicode(false) + .HasComment("Ip"); + entity.Property(e => e.NickName) + .HasMaxLength(50) + .HasComment("鐢ㄦ埛鏄电О锛岄渶瑕佸拰涓昏〃淇濇寔涓鑷"); + entity.Property(e => e.UpdatedAt) + .HasComment("鏇存柊鏃堕棿") + .HasColumnType("datetime"); + entity.Property(e => e.UserIconUrl) + .HasMaxLength(300) + .HasComment("鐢ㄦ埛澶村儚"); + entity.Property(e => e.VipType).HasComment("vip绫诲瀷"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_User_P__3214EC07987BDDB2"); + + entity.ToTable(tb => tb.HasComment("鎵嬫満鍙风櫥褰曡〃")); + + entity.Property(e => e.Id).HasComment("涓婚敭"); + entity.Property(e => e.CreatedAt) + .HasComment("淇敼鏃堕棿") + .HasColumnType("datetime"); + entity.Property(e => e.LastLoginAt) + .HasComment("鏈鍚庝竴娆$櫥褰曟椂闂") + .HasColumnType("datetime"); + entity.Property(e => e.NikeName) + .HasMaxLength(1) + .HasComment("鐢ㄦ埛鏄电О"); + entity.Property(e => e.PhoneNum) + .HasMaxLength(50) + .IsUnicode(false) + .HasComment("鎵嬫満鍙"); + entity.Property(e => e.TenantId).HasComment("绉熸埛Id"); + entity.Property(e => e.UpdatedAt) + .HasComment("鍒涘缓鏃堕棿") + .HasColumnType("datetime"); + entity.Property(e => e.UserId).HasComment("鐢ㄦ埛Id"); + entity.Property(e => e.VerificationCode) + .HasMaxLength(10) + .IsUnicode(false) + .HasComment("楠岃瘉鐮"); + }); + + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User.cs new file mode 100644 index 0000000..63160fd --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User.cs @@ -0,0 +1,65 @@ +锘縰sing System; + +namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; + +/// +/// 鐢ㄦ埛琛 +/// +public partial class T_User: MultiTenantEntity +{ + /// + /// 鐢ㄦ埛Id + /// + public int Id { get; set; } + + + /// + /// 鐢ㄦ埛鏄电О + /// + public string NickName { get; set; } = null!; + + /// + /// 鐢ㄦ埛濮撳悕 + /// + public string? UserName { get; set; } + + /// + /// 缁戝畾鐨勬墜鏈哄彿 + /// + public string? PhoneNum { get; set; } + + /// + /// 缁戝畾鐨勯偖绠 + /// + public string? Email { get; set; } + + /// + /// 鏄惁娲昏穬 + /// + public bool IsActive { get; set; } + + /// + /// 鍒涘缓鏃堕棿 + /// + public DateTime CreatedAt { get; set; } + + /// + /// 鏈鍚庝竴娆$櫥褰曟柟寮,1鎵嬫満鍙 + /// + public int LastLoginTypeAt { get; set; } + + /// + /// 鏈鍚庝竴娆$櫥褰曟椂闂 + /// + public DateTime LastLoginAt { get; set; } + + /// + /// 淇敼鏃堕棿 + /// + public DateTime UpdatedAt { get; set; } + + /// + /// 棣栨娉ㄥ唽鏂瑰紡 + /// + public int RegisterType { get; set; } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Data.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Data.cs new file mode 100644 index 0000000..057e8b9 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Data.cs @@ -0,0 +1,55 @@ +锘縰sing System; + +namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; + +/// +/// 鐢ㄦ埛淇℃伅琛 +/// +public partial class T_User_Data: MultiTenantEntity +{ + /// + /// 涓婚敭 + /// + public int Id { get; set; } + + /// + /// 鐢ㄦ埛Id + /// + public int UserId { get; set; } + + + /// + /// 鐢ㄦ埛鏄电О锛岄渶瑕佸拰涓昏〃淇濇寔涓鑷 + /// + public string? NickName { get; set; } + + /// + /// vip绫诲瀷 + /// + public int VipType { get; set; } + + /// + /// 璐у竵 + /// + public int Currency { get; set; } + + /// + /// 鐢ㄦ埛澶村儚 + /// + public string? UserIconUrl { get; set; } + + /// + /// 鍒涘缓鏃堕棿 + /// + public DateTime CreatedAt_ { get; set; } + + /// + /// 鏇存柊鏃堕棿 + /// + public DateTime UpdatedAt { get; set; } + + /// + /// Ip + /// + public string? IP { get; set; } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Phone_Account.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Phone_Account.cs new file mode 100644 index 0000000..7ee3d0a --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Phone_Account.cs @@ -0,0 +1,50 @@ +锘縰sing System; + +namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu; + +/// +/// 鎵嬫満鍙风櫥褰曡〃 +/// +public partial class T_User_Phone_Account: MultiTenantEntity +{ + /// + /// 涓婚敭 + /// + public int Id { get; set; } + + + /// + /// 鐢ㄦ埛Id + /// + public int UserId { get; set; } + + /// + /// 鎵嬫満鍙 + /// + public string PhoneNum { get; set; } = null!; + + /// + /// 楠岃瘉鐮 + /// + public string VerificationCode { get; set; } = null!; + + /// + /// 鏈鍚庝竴娆$櫥褰曟椂闂 + /// + public DateTime LastLoginAt { get; set; } + + /// + /// 淇敼鏃堕棿 + /// + public DateTime CreatedAt { get; set; } + + /// + /// 鍒涘缓鏃堕棿 + /// + public DateTime UpdatedAt { get; set; } + + /// + /// 鐢ㄦ埛鏄电О + /// + public string? NikeName { get; set; } +} diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/efcore-gen.md b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/efcore-gen.md new file mode 100644 index 0000000..b9693fe --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/efcore-gen.md @@ -0,0 +1,5 @@ +锘 +##鍦ˋPI椤圭洰閲岄潰鎵ц锛屼娇鐢ㄨ繛鎺ュ瓧绗︿覆鍚嶇О锛岀敓鎴愪唬鐮佸埌model椤圭洰 +```sh +dotnet ef dbcontext scaffold "Server=192.168.195.2;Database=MiaoYu;User Id=zpc;Password=zpc;TrustServerCertificate=true;" Microsoft.EntityFrameworkCore.SqlServer -o DbSqlServer/Db_MiaoYu/ --use-database-names --no-pluralize --force +``` \ No newline at end of file diff --git a/src/0-core/HuanMeng.MiaoYu.Model/GlobalUsings.cs b/src/0-core/HuanMeng.MiaoYu.Model/GlobalUsings.cs new file mode 100644 index 0000000..0a7e25b --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/GlobalUsings.cs @@ -0,0 +1,2 @@ +global using HuanMeng.DotNetCore.MultiTenant; +global using HuanMeng.DotNetCore.MultiTenant.Contract; diff --git a/src/0-core/HuanMeng.MiaoYu.Model/HuanMeng.MiaoYu.Model.csproj b/src/0-core/HuanMeng.MiaoYu.Model/HuanMeng.MiaoYu.Model.csproj new file mode 100644 index 0000000..2b25295 --- /dev/null +++ b/src/0-core/HuanMeng.MiaoYu.Model/HuanMeng.MiaoYu.Model.csproj @@ -0,0 +1,32 @@ +锘 + + + net8.0 + enable + enable + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + +