Browse Source

feat: 添加code命令

feat/cap 9.0.6.8
Hanpaopao 1 year ago
parent
commit
f3e1d4bfd2
  1. 1
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/GlobalUsings.cs
  2. 6
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion.AbpPro.Cli.Core.csproj
  3. 1
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/AbpProCliCoreModule.cs
  4. 47
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Args/CommandOptions.cs
  5. 41
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Auth/ConfigService.cs
  6. 14
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Auth/IConfigService.cs
  7. 1
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/CliPaths.cs
  8. 6
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/CliService.cs
  9. 145
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/CodeService.cs
  10. 205
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/CodeCommand.cs
  11. 73
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/ConfigCommand.cs
  12. 3
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/CreateCommand.cs
  13. 6
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/NewCommand.cs
  14. 15
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Dto/ErrorResponse.cs
  15. 8
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Dto/FindTenantResponse.cs
  16. 54
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Dto/GetProjectAndEntityResponse.cs
  17. 1
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Github/AbpProManager.cs
  18. 13
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/ICodeService.cs
  19. 14
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Options/ConfigOptions.cs
  20. 154
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Utils/CodeHelper.cs
  21. 77
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Utils/DirectoryHelper.cs
  22. 2
      aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Utils/ZipHelper.cs
  23. 2
      aspnet-core/services/src/Lion.AbpPro.Domain/AbpProDbProperties.cs
  24. 12
      aspnet-core/services/src/Lion.AbpPro.EntityFrameworkCore/EntityFrameworkCore/AbpProDbContext.cs
  25. 22
      aspnet-core/services/src/Lion.AbpPro.EntityFrameworkCore/EntityFrameworkCore/AbpProDbContextModelCreatingExtensions.cs
  26. 4
      templates/pro-nuget/service/src/MyCompanyName.MyProjectName.Domain/MyProjectNameProperties.cs
  27. 9
      templates/pro-nuget/service/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameDbContext.cs
  28. 22
      templates/pro-nuget/service/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameDbContextModelCreatingExtensions.cs

1
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/GlobalUsings.cs

@ -18,6 +18,7 @@ global using Microsoft.Extensions.Options;
global using Octokit;
global using Polly;
global using Polly.Retry;
global using Spectre.Console;
global using Volo.Abp;
global using Volo.Abp.DependencyInjection;
global using Volo.Abp.Domain;

6
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion.AbpPro.Cli.Core.csproj

@ -11,14 +11,12 @@
<PackageReference Include="Microsoft.Extensions.Http" />
<PackageReference Include="Octokit" Version="14.0.0"/>
<PackageReference Include="Polly" />
<PackageReference Include="Spectre.Console" Version="0.49.1" />
<PackageReference Include="Volo.Abp.Ddd.Domain" />
<PackageReference Include="Volo.Abp.Autofac" />
<PackageReference Include="Volo.Abp.Threading" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
</ItemGroup>
<ItemGroup>
<Folder Include="Lion\AbpPro\Cli\SourceCode\" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
</ItemGroup>
</Project>

1
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/AbpProCliCoreModule.cs

@ -12,6 +12,7 @@ public class AbpProCliCoreModule : AbpModule
Configure<AbpCliOptions>(options => { options.Commands[LoginCommand.Name] = typeof(LoginCommand); });
Configure<AbpCliOptions>(options => { options.Commands[CreateCommand.Name] = typeof(CreateCommand); });
Configure<AbpCliOptions>(options => { options.Commands[CodeCommand.Name] = typeof(CodeCommand); });
Configure<AbpCliOptions>(options => { options.Commands[ConfigCommand.Name] = typeof(ConfigCommand); });
Configure<Options.AbpProCliOptions>(options =>
{

47
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Args/CommandOptions.cs

@ -67,11 +67,56 @@ public static class CommandOptions
}
/// <summary>
/// 版本
/// Token
/// </summary>
public static class Token
{
public const string Short = "token";
public const string Long = "token";
}
/// <summary>
/// 版本
/// </summary>
public static class Sln
{
public const string Short = "sln";
public const string Long = "sln";
}
/// <summary>
/// UserName
/// </summary>
public static class UserName
{
public const string Short = "u";
public const string Long = "UserName";
}
/// <summary>
/// Password
/// </summary>
public static class Password
{
public const string Short = "p";
public const string Long = "Password";
}
/// <summary>
/// 版本
/// </summary>
public static class TenantName
{
public const string Short = "t";
public const string Long = "TenantName";
}
/// <summary>
/// CodeServiceUrl
/// </summary>
public static class CodeServiceUrl
{
public const string Short = "c";
public const string Long = "CodeServiceUrl";
}
}

41
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Auth/ConfigService.cs

@ -0,0 +1,41 @@
using System.Text.Json;
namespace Lion.AbpPro.Cli.Auth;
public class ConfigService : IConfigService, ITransientDependency
{
private readonly IJsonSerializer _jsonSerializer;
public ConfigService(IJsonSerializer jsonSerializer)
{
_jsonSerializer = jsonSerializer;
}
public async Task SetAsync(string config)
{
if (!Directory.Exists(CliPaths.Root))
{
Directory.CreateDirectory(CliPaths.Root);
}
await File.WriteAllTextAsync(CliPaths.Config, config, Encoding.UTF8);
}
public async Task<ConfigOptions> GetAsync()
{
if (!File.Exists(CliPaths.Config))
{
return new ConfigOptions()
{
CodeServiceUrl = "http://182.43.18.151:44317",
UserName = "admin",
Password = "1q2w3E*",
TenantName = string.Empty,
TenantId = string.Empty
};
}
var content = await File.ReadAllTextAsync(CliPaths.Config);
return _jsonSerializer.Deserialize<ConfigOptions>(content);
}
}

14
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Auth/IConfigService.cs

@ -0,0 +1,14 @@
namespace Lion.AbpPro.Cli.Auth;
public interface IConfigService
{
/// <summary>
/// 设置token
/// </summary>
Task SetAsync(string config);
/// <summary>
/// 获取token
/// </summary>
Task<ConfigOptions> GetAsync();
}

1
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/CliPaths.cs

@ -6,6 +6,7 @@ public class CliPaths
public static string Root => Path.Combine(AbpRootPath, "cli");
public static string AccessToken => Path.Combine(AbpRootPath, "cli", "access-token.bin");
public static string Config => Path.Combine(AbpRootPath, "cli", "config.bin");
public static string Output => Path.Combine(AbpRootPath, "cli", "code", "output");
public static string Source => Path.Combine(AbpRootPath, "cli", "code", "source");

6
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/CliService.cs

@ -20,8 +20,8 @@ public class CliService : DomainService
public async Task RunAsync(string[] args)
{
Logger.LogInformation("ABP Pro CLI (http://doc.cncore.club/)");
Logger.LogInformation("请输入 lion.abp help 查看所有命令");
AnsiConsole.MarkupLine("[green]ABP Pro CLI (http://doc.cncore.club/)[/]");
AnsiConsole.MarkupLine("[green]请输入lion.abp help 查看所有命令[/]");
try
{
var commandLineArgs = _commandLineArgumentParser.Parse(args);
@ -30,7 +30,7 @@ public class CliService : DomainService
catch (Exception ex)
{
Logger.LogError(ex.Message);
AnsiConsole.MarkupLine($"[red]{ex.Message}[/]");
}
}

145
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/CodeService.cs

@ -1,3 +1,4 @@
using Lion.AbpPro.Cli.Auth;
using Lion.AbpPro.Cli.Dto;
using FileMode = System.IO.FileMode;
@ -8,71 +9,171 @@ public class CodeService : ICodeService, ITransientDependency
private readonly ILogger<CodeService> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IJsonSerializer _jsonSerializer;
private readonly IConfigService _configService;
public CodeService(ILogger<CodeService> logger, IHttpClientFactory httpClientFactory, IJsonSerializer jsonSerializer)
public CodeService(ILogger<CodeService> logger, IHttpClientFactory httpClientFactory, IJsonSerializer jsonSerializer, IConfigService configService)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
_jsonSerializer = jsonSerializer;
_configService = configService;
}
public async Task<string> GetAccessTokenAsync()
private async Task<ConfigOptions> GetConfigOptionsAsync()
{
return await _configService.GetAsync();
}
private async Task<HttpClient> GetHttpClientAsync()
{
var options = await GetConfigOptionsAsync();
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(options.CodeServiceUrl);
return httpClient;
}
public async Task<string> LoginAsync(string url, string userName, string password)
{
using var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri("http://182.43.18.151:44317/");
httpClient.BaseAddress = new Uri(url);
var data = new
{
name = "admin",
password = "1q2w3E*"
name = userName,
password = password
};
var content = new StringContent(_jsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("/api/app/account/login", content);
if (response.IsSuccessStatusCode)
if (!response.IsSuccessStatusCode)
{
_logger.LogInformation($"登录代码生成器服务成功");
throw new UserFriendlyException($"用户或者密码错误");
}
else
return _jsonSerializer.Deserialize<LoginResponse>(await response.Content.ReadAsStringAsync()).Token;
}
public async Task<string> GetAccessTokenAsync()
{
var options = await GetConfigOptionsAsync();
using var httpClient = await GetHttpClientAsync();
var data = new
{
_logger.LogError($"登录代码生成器服务失败,状态码{response.StatusCode}");
name = options.UserName,
password = options.Password
};
httpClient.DefaultRequestHeaders.Add("__tenant", $"{options.TenantId}");
var content = new StringContent(_jsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("/api/app/account/login", content);
if (!response.IsSuccessStatusCode)
{
throw new UserFriendlyException($"用户或者密码错误");
}
return _jsonSerializer.Deserialize<LoginResponse>(await response.Content.ReadAsStringAsync()).Token;
}
public async Task<string> DownloadAsync(string accessToken, Guid projectId, Guid templateId)
public async Task<string> DownloadAsync(string accessToken, Guid projectId, Guid templateId, List<Guid> entityId)
{
var options = await GetConfigOptionsAsync();
var path = Path.Combine(CliPaths.Source, $"{templateId}_{projectId}.zip");
if (File.Exists(path))
{
File.Delete(path);
}
using var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri("http://182.43.18.151:44317/");
using var httpClient = await GetHttpClientAsync();
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
// 3a179906-5c79-b1e8-69f6-872afc276592
// 3a18123b-4ac4-b8e7-ddb8-73ac01179aff
httpClient.DefaultRequestHeaders.Add("__tenant", $"{options.TenantId}");
var data = new
{
templateId = templateId,
projectId = projectId
projectId = projectId,
entityId = entityId
};
var content = new StringContent(_jsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("/Generator/Down", content);
if (response.IsSuccessStatusCode)
if (!response.IsSuccessStatusCode)
{
_logger.LogInformation($"下载代码成功");
}
else
{
_logger.LogError($"下载代码失败,状态码{response.StatusCode}");
throw new UserFriendlyException($"下载代码失败,状态码{response.StatusCode}");
}
// 保存到本地
await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
await response.Content.CopyToAsync(fileStream);
_logger.LogInformation($"保存代码成功");
return path;
}
public async Task<GetProjectAndEntityResponse> GetProjectAndEntityAsync(string accessToken, Guid projectId)
{
var options = await GetConfigOptionsAsync();
using var httpClient = await GetHttpClientAsync();
var data = new
{
id = projectId,
};
var content = new StringContent(_jsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
httpClient.DefaultRequestHeaders.Add("__tenant", $"{options.TenantId}");
var response = await httpClient.PostAsync("/Projects/GetProjectAndEntity", content);
if (!response.IsSuccessStatusCode)
{
var error = _jsonSerializer.Deserialize<ErrorResponse>(await response.Content.ReadAsStringAsync());
throw new UserFriendlyException(error.error.message);
}
return _jsonSerializer.Deserialize<GetProjectAndEntityResponse>(await response.Content.ReadAsStringAsync());
}
public async Task<FindTenantResponse> FindTenantAsync(string url, string tenantName)
{
using var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = GetUri(url);
var data = new
{
name = tenantName,
};
var content = new StringContent(_jsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("Tenants/find", content);
if (!response.IsSuccessStatusCode)
{
var error = _jsonSerializer.Deserialize<ErrorResponse>(await response.Content.ReadAsStringAsync());
throw new UserFriendlyException(error.error.message);
}
var result = _jsonSerializer.Deserialize<FindTenantResponse>(await response.Content.ReadAsStringAsync());
if (!result.Success)
{
throw new UserFriendlyException($"租户不存在:{tenantName}");
}
return result;
}
public async Task CheckHealthAsync(string url)
{
using var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = GetUri(url);
var response = await httpClient.GetAsync("/health");
if (!response.IsSuccessStatusCode)
{
throw new UserFriendlyException($"服务异常:{url}");
}
}
private Uri GetUri(string url)
{
Uri uri;
try
{
uri = new Uri(url);
}
catch (Exception e)
{
throw new UserFriendlyException($"url格式错误:{url}");
}
return uri;
}
}

205
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/CodeCommand.cs

@ -1,8 +1,12 @@
using Lion.AbpPro.Cli.Dto;
namespace Lion.AbpPro.Cli.Commands;
public class CodeCommand : IConsoleCommand, ITransientDependency
{
public const string Name = "code";
private const string Dotnet = "dotnet";
private const string Vue3 = "vue3";
private readonly ILogger<CodeCommand> _logger;
private readonly ICodeService _codeService;
@ -12,25 +16,218 @@ public class CodeCommand : IConsoleCommand, ITransientDependency
_logger = logger;
}
/// <summary>
/// code -p 3a1821f9-9c71-4d5e-205e-008267cee6b9 -t 3a182572-1a21-ffd4-db9d-4d6065c4eac8 -s C:\Users\Administrator\.abp.pro\cli\code\output\ErpOA9.1.1-rc3\src
/// </summary>
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
var template = commandLineArgs.Options.GetOrNull(CommandOptions.Template.Short, CommandOptions.Template.Long);
var project = commandLineArgs.Options.GetOrNull(CommandOptions.Project.Short, CommandOptions.Project.Long);
var accessToken = await _codeService.GetAccessTokenAsync();
var source = commandLineArgs.Options.GetOrNull(CommandOptions.Source.Short, CommandOptions.Source.Long);
source = source.IsNullOrWhiteSpace() ? Directory.GetCurrentDirectory() : source;
if (Guid.TryParse(template, out Guid templateId) && Guid.TryParse(project, out Guid projectId))
{
var path = await _codeService.DownloadAsync(accessToken, projectId, templateId);
ZipHelper.Extract(path);
// 生成后端代码还是前端代码
var type = AnsiConsole.Prompt(new SelectionPrompt<string>().Title("请选择生成的代码?").AddChoices(new[]
{
Dotnet,
Vue3
}));
if (type == Dotnet)
{
await GenerateBackCode(projectId, templateId, source);
}
else if (type == Vue3)
{
await GenerateFrontCode(projectId, templateId, source);
}
AnsiConsole.MarkupLine("[green]恭喜你,代码生成成功,请打开项目检查![/]");
}
else
{
Console.WriteLine("输入的模板 ID 或项目 ID 不是有效的 GUID 格式,请检查后重新输入。");
AnsiConsole.MarkupLine("[red]输入的模板 ID 或项目 ID 不是有效的 GUID 格式,请检查后重新输入。[/]");
}
}
private async Task<GetProjectAndEntityResponse> GetProjectAsync(string accessToken, Guid projectId)
{
var project = await _codeService.GetProjectAndEntityAsync(accessToken, projectId);
if (project.Entities.Count == 0)
{
throw new UserFriendlyException("当前项目未定义实体");
}
return project;
}
/// <summary>
/// 生成后端代码
/// // https://spectreconsole.net/prompts/multiselection
/// </summary>
private async Task GenerateBackCode(Guid projectId, Guid templateId, string sourcePath)
{
var accessToken = await _codeService.GetAccessTokenAsync();
// 获取项目信息
var project = await GetProjectAsync(accessToken, projectId);
//判断是否是标准abp的项目结构方式
Utils.DirectoryHelper.IsAbpProjectStructure(sourcePath, project.Project.CompanyName, project.Project.ProjectName);
// 可以选择需要生成的实体
var entities = AnsiConsole.Prompt(
new MultiSelectionPrompt<string>()
.Title("请选择需要生成的实体")
.Required()
.InstructionsText(
"[grey](按下空格键 [blue]<space>[/]切换是否选中, " +
"[white]上下建切换,[/] " +
"[green]按下回车键<enter>[/]确认)[/]")
.AddChoices(project.Entities.Select(e => e.Code)));
// 获取选中的实体信息
var entityId = project.Entities.Where(e => entities.Contains(e.Code)).Select(p => p.Id).ToList();
// 下载代码
var path = await _codeService.DownloadAsync(accessToken, projectId, templateId, entityId);
// 解压下载的代码
var extractPath = ZipHelper.Extract(path);
// 遍历选中实体生成对应层级的代码
foreach (var id in entityId)
{
var item = project.Entities.First(e => e.Id == id);
GenerateCode(extractPath, sourcePath, "Domain.Shared", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
GenerateCode(extractPath, sourcePath, "Domain", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
GenerateCode(extractPath, sourcePath, "Application.Contracts", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
GenerateCode(extractPath, sourcePath, "Application", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
GenerateCode(extractPath, sourcePath, "HttpApi", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
AppendIDbContextCode(extractPath, sourcePath, "EntityFrameworkCore", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
AppendDbContextCode(extractPath, sourcePath, "EntityFrameworkCore", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
AppendDbContextModelCreatingExtensionsCode(extractPath, sourcePath, "EntityFrameworkCore", item.CodePluralized, project.Project.CompanyName, project.Project.ProjectName);
}
}
/// <summary>
/// 生成前端代码
/// </summary>
private async Task GenerateFrontCode(Guid projectId, Guid templateId, string sourcePath)
{
var accessToken = await _codeService.GetAccessTokenAsync();
// 获取项目信息
var project = await GetProjectAsync(accessToken, projectId);
//判断是否是标准vben5的项目结构方式
Utils.DirectoryHelper.IsVben5ProjectStructure(sourcePath);
// 可以选择需要生成的实体
var entities = AnsiConsole.Prompt(
new MultiSelectionPrompt<string>()
.Title("请选择需要生成的实体")
.Required()
.InstructionsText(
"[grey](按下空格键 [blue]<space>[/]切换是否选中, " +
"[white]上下建切换,[/] " +
"[green]按下回车键<enter>[/]确认)[/]")
.AddChoices(project.Entities.Select(e => e.Code)));
// 获取选中的实体信息
var entityId = project.Entities.Where(e => entities.Contains(e.Code)).Select(p => p.Id).ToList();
// 下载代码
var path = await _codeService.DownloadAsync(accessToken, projectId, templateId, entityId);
// 解压下载的代码
var extractPath = ZipHelper.Extract(path);
// 遍历选中实体生成对应层级的代码
foreach (var id in entityId)
{
var item = project.Entities.First(e => e.Id == id);
var sourceCodePath = Path.Combine(extractPath, "Vben5", "routes", item.CodePluralized);
var targetCodePath = Path.Combine(sourcePath, "router", "routes", "modules");
Utils.DirectoryHelper.CopyFolder(sourceCodePath, targetCodePath);
var sourceViewCodePath = Path.Combine(extractPath, "Vben5", "views", item.CodePluralized);
var targetViewCodePath = Path.Combine(sourcePath, "views", item.CodePluralized);
Utils.DirectoryHelper.CopyFolder(sourceViewCodePath, targetViewCodePath);
}
}
private void GenerateCode(string templateSourceCodePath, string sourcePath, string type, string entityCodePluralized, string companyName, string projectName)
{
var sourceCodePath = Path.Combine(templateSourceCodePath, "AspNetCore", "src", type, entityCodePluralized);
var targetCodePath = Path.Combine(sourcePath, $"{companyName}.{projectName}.{type}", entityCodePluralized);
Utils.DirectoryHelper.CopyFolder(sourceCodePath, targetCodePath);
}
private void AppendIDbContextCode(string templateSourceCodePath, string sourcePath, string type, string entityCodePluralized, string companyName, string projectName)
{
var basePath = Path.Combine(templateSourceCodePath, "AspNetCore", "src", type);
// 给IDbContext追加dbset
var sourceCodePath = Path.Combine(basePath, $"I{projectName}DbContext.cs");
var code = File.ReadAllText(sourceCodePath);
var targetCodePath = Path.Combine(sourcePath, $"{companyName}.{projectName}.{type}", type, $"I{projectName}DbContext.cs");
// 判断代码是否已经生成
if (CodeHelper.IsExistCode(targetCodePath, code))
{
return;
}
Utils.CodeHelper.AddCodeToInterface(targetCodePath, $"I{projectName}DbContext", code);
CodeHelper.AddUsing(targetCodePath, $"using {companyName}.{projectName}.{entityCodePluralized};");
}
private void AppendDbContextCode(string templateSourceCodePath, string sourcePath, string type, string entityCodePluralized, string companyName, string projectName)
{
var basePath = Path.Combine(templateSourceCodePath, "AspNetCore", "src", type);
// 给DbContext追加dbset
var dbContextCodePath = Path.Combine(basePath, $"{projectName}DbContext.cs");
var dbContextCode = File.ReadAllText(dbContextCodePath);
var targetDbContextCodePath = Path.Combine(sourcePath, $"{companyName}.{projectName}.{type}", type, $"{projectName}DbContext.cs");
// 判断代码是否已经生成
if (CodeHelper.IsExistCode(targetDbContextCodePath, dbContextCode))
{
return;
}
Utils.CodeHelper.AddCodeToClass(targetDbContextCodePath, $"{projectName}DbContext", dbContextCode);
CodeHelper.AddUsing(targetDbContextCodePath, $"using {companyName}.{projectName}.{entityCodePluralized};");
}
private void AppendDbContextModelCreatingExtensionsCode(string templateSourceCodePath, string sourcePath, string type, string entityCodePluralized, string companyName, string projectName)
{
var basePath = Path.Combine(templateSourceCodePath, "AspNetCore", "src", type);
// 给ContextModelCreatingExtensions追加ef 配置
var dbContextModelCreatingExtensionsPath = Path.Combine(basePath, $"{projectName}DbContextModelCreatingExtensions.cs");
var dbContextModelCreatingExtensionsCode = File.ReadAllText(dbContextModelCreatingExtensionsPath);
var targetDbContextModelCreatingExtensionsCodePath = Path.Combine(sourcePath, $"{companyName}.{projectName}.{type}", type, $"{projectName}DbContextModelCreatingExtensions.cs");
// 判断代码是否已经生成
if (CodeHelper.IsExistCode(targetDbContextModelCreatingExtensionsCodePath, dbContextModelCreatingExtensionsCode))
{
return;
}
Utils.CodeHelper.AddCodeToMethod(targetDbContextModelCreatingExtensionsCodePath, $"Configure{projectName}", dbContextModelCreatingExtensionsCode);
CodeHelper.AddUsing(targetDbContextModelCreatingExtensionsCodePath, $"using {companyName}.{projectName}.{entityCodePluralized};");
}
public void GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine(" lion.abp create");
sb.AppendLine("lion.abp create -t 模板名称(source | nuget) -c 公司名称 -p 项目名称");
AnsiConsole.MarkupLine($"[green]{sb.ToString()}[/]");
}
public string GetShortDescription()

73
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/ConfigCommand.cs

@ -0,0 +1,73 @@
using Lion.AbpPro.Cli.Auth;
namespace Lion.AbpPro.Cli.Commands;
public class ConfigCommand : IConsoleCommand, ITransientDependency
{
public const string Name = "config";
private readonly ILogger<ConfigCommand> _logger;
private readonly IConfigService _configService;
private readonly IJsonSerializer _jsonSerializer;
private readonly ICodeService _codeService;
public ConfigCommand(ILogger<ConfigCommand> logger, IConfigService configService, IJsonSerializer jsonSerializer, ICodeService codeService)
{
_logger = logger;
_configService = configService;
_jsonSerializer = jsonSerializer;
_codeService = codeService;
}
/// <summary>
/// config -c http://182.43.18.151:44317 -u admin -p 1q2w3E* -t ss
/// </summary>
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
// 获取参数
var url = commandLineArgs.Options.GetOrNull(CommandOptions.CodeServiceUrl.Short, CommandOptions.CodeServiceUrl.Long);
var userName = commandLineArgs.Options.GetOrNull(CommandOptions.UserName.Short, CommandOptions.UserName.Long);
var password = commandLineArgs.Options.GetOrNull(CommandOptions.Password.Short, CommandOptions.Password.Long);
var tenantName = commandLineArgs.Options.GetOrNull(CommandOptions.TenantName.Short, CommandOptions.TenantName.Long);
//1 判断url是否有效
await _codeService.CheckHealthAsync(url);
var tenantId = string.Empty;
//2 判断租户是否存在
if (!tenantName.IsNullOrWhiteSpace())
{
var tenant = await _codeService.FindTenantAsync(url, tenantName);
tenantId = tenant.TenantId.ToString();
}
//3. 判断用户是否存在
await _codeService.LoginAsync(url, userName, password);
var content = new ConfigOptions()
{
CodeServiceUrl = url,
UserName = userName,
Password = password,
TenantName = tenantName,
TenantId = tenantId
};
await _configService.SetAsync(_jsonSerializer.Serialize(content));
AnsiConsole.MarkupLine("[green]恭喜你,恭喜你设置config成功![/]");
}
public void GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine(" lion.abp config");
sb.AppendLine("");
sb.AppendLine("配置: lion.abp config");
_logger.LogInformation(sb.ToString());
}
public string GetShortDescription()
{
return "配置: lion.abp config -c http://182.43.18.151:44317 -u admin -p 1q2w3E* -t test";
}
}

3
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/CreateCommand.cs

@ -1,4 +1,5 @@
using Lion.AbpPro.Cli.Auth;
using DirectoryHelper = Lion.AbpPro.Cli.Utils.DirectoryHelper;
namespace Lion.AbpPro.Cli.Commands;
@ -116,7 +117,7 @@ public class CreateCommand : IConsoleCommand, ITransientDependency
DirectoryAndFileHelper.CopyFolder(contentPath, output, templateOptions.ExcludeFiles);
DirectoryHelper.CopyFolder(contentPath, output, templateOptions.ExcludeFiles);
ReplaceHelper.ReplaceTemplates(
output,

6
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Commands/NewCommand.cs

@ -1,4 +1,6 @@
namespace Lion.AbpPro.Cli.Commands;
using DirectoryHelper = Lion.AbpPro.Cli.Utils.DirectoryHelper;
namespace Lion.AbpPro.Cli.Commands;
public class NewCommand : IConsoleCommand, ITransientDependency
{
@ -126,7 +128,7 @@ public class NewCommand : IConsoleCommand, ITransientDependency
}
DirectoryAndFileHelper.CopyFolder(contentPath, output, templateOptions.ExcludeFiles);
DirectoryHelper.CopyFolder(contentPath, output, templateOptions.ExcludeFiles);
ReplaceHelper.ReplaceTemplates(
output,

15
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Dto/ErrorResponse.cs

@ -0,0 +1,15 @@
namespace Lion.AbpPro.Cli.Dto;
public class ErrorResponse
{
public Error error { get; set; }
}
public class Error
{
public object code { get; set; }
public string message { get; set; }
public object details { get; set; }
public object data { get; set; }
public object validationErrors { get; set; }
}

8
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Dto/FindTenantResponse.cs

@ -0,0 +1,8 @@
namespace Lion.AbpPro.Cli.Dto;
public class FindTenantResponse
{
public Guid? TenantId { get; set; }
public bool Success { get; set; }
}

54
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Dto/GetProjectAndEntityResponse.cs

@ -0,0 +1,54 @@
namespace Lion.AbpPro.Cli.Dto;
public class GetProjectAndEntityResponse
{
public GetProjectAndEntityResponse()
{
Entities = new List<EntityOutput>();
}
public ProjectOutput Project { get; set; }
public List<EntityOutput> Entities { get; set; }
}
public class ProjectOutput
{
public Guid Id { get; set; }
/// <summary>
/// 公司名称
/// </summary>
public string CompanyName { get; set; }
/// <summary>
/// 项目名称
/// </summary>
public string ProjectName { get; set; }
}
public class EntityOutput
{
public Guid Id { get; set; }
/// <summary>
/// 编码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 首字母小写
/// </summary>
public string CodeCamelCase { get; set; }
/// <summary>
/// 复数形式
/// </summary>
public string CodePluralized { get; set; }
}

1
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Github/AbpProManager.cs

@ -1,3 +1,4 @@
using DirectoryHelper = Volo.Abp.IO.DirectoryHelper;
using Uri = System.Uri;
namespace Lion.AbpPro.Cli.Github;

13
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/ICodeService.cs

@ -1,8 +1,19 @@
using Lion.AbpPro.Cli.Dto;
namespace Lion.AbpPro.Cli;
public interface ICodeService
{
Task<string> GetAccessTokenAsync();
Task<string> DownloadAsync(string accessToken, Guid projectId, Guid templateId);
Task<string> DownloadAsync(string accessToken, Guid projectId, Guid templateId, List<Guid> entityId);
Task<GetProjectAndEntityResponse> GetProjectAndEntityAsync(string accessToken, Guid projectId);
Task CheckHealthAsync(string url);
Task<FindTenantResponse> FindTenantAsync(string url, string tenantName);
Task<string> LoginAsync(string url, string userName, string password);
}

14
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Options/ConfigOptions.cs

@ -0,0 +1,14 @@
namespace Lion.AbpPro.Cli.Options;
public class ConfigOptions
{
public string CodeServiceUrl { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string TenantName { get; set; }
public string TenantId { get; set; }
}

154
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Utils/CodeHelper.cs

@ -0,0 +1,154 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
namespace Lion.AbpPro.Cli.Utils;
public static class CodeHelper
{
/// <summary>
/// 把指定代码添加到对应方法中
/// </summary>
public static void AddCodeToMethod(string filePath, string methodName, string addCode)
{
try
{
// 读取文件内容
var code = File.ReadAllText(filePath);
// 解析代码为语法树
var tree = CSharpSyntaxTree.ParseText(code);
var root = tree.GetCompilationUnitRoot();
// 查找所有的方法声明
var methodDeclarations = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
// 筛选出名为 ConfigureOA 的方法
var configureOAMethod = methodDeclarations.FirstOrDefault(m => m.Identifier.ValueText == methodName);
if (configureOAMethod == null) return;
// 解析要添加的代码为语句
var newStatement = CSharpSyntaxTree.ParseText(addCode).GetCompilationUnitRoot().DescendantNodes().OfType<StatementSyntax>().FirstOrDefault();
if (newStatement == null) return;
// 在方法体中添加新语句
var newMethodBody = configureOAMethod?.Body?.AddStatements(newStatement);
var newMethod = configureOAMethod.WithBody(newMethodBody);
// 替换原方法为新方法
var newRoot = root.ReplaceNode(configureOAMethod, newMethod);
// 获取更新后的代码文本
var newCode = newRoot.GetText().ToString();
// 将更新后的代码写回文件
File.WriteAllText(filePath, newCode);
}
catch (Exception ex)
{
throw new UserFriendlyException($"发生错误AddCodeToMethod: {ex.Message}");
}
}
public static void AddCodeToClass(string filePath, string className, string addCode)
{
try
{
// 读取文件内容
var code = File.ReadAllText(filePath);
// 解析代码为语法树
var tree = CSharpSyntaxTree.ParseText(code);
var root = tree.GetCompilationUnitRoot();
// 查找 IOADbContext 接口声明
var interfaceDeclaration = root.DescendantNodes().OfType<ClassDeclarationSyntax>()
.FirstOrDefault(i => i.Identifier.ValueText == className);
if (interfaceDeclaration == null) return;
// 解析要添加的属性代码
var newProperty = CSharpSyntaxTree.ParseText(addCode).GetCompilationUnitRoot()
.DescendantNodes().OfType<PropertyDeclarationSyntax>().FirstOrDefault();
if (newProperty == null) return;
// 在接口成员中添加新属性
var newMembers = interfaceDeclaration.Members.Add(newProperty);
var newInterface = interfaceDeclaration.WithMembers(newMembers);
// 替换原接口声明为新接口声明
var newRoot = root.ReplaceNode(interfaceDeclaration, newInterface);
// 获取更新后的代码文本
var newCode = newRoot.GetText().ToString();
// 将更新后的代码写回文件
File.WriteAllText(filePath, newCode);
}
catch (Exception ex)
{
throw new UserFriendlyException($"发生错误AddCodeToClass: {ex.Message}");
}
}
public static void AddCodeToInterface(string filePath, string interfaceName, string addCode)
{
try
{
// 读取文件内容
var code = File.ReadAllText(filePath);
// 解析代码为语法树
var tree = CSharpSyntaxTree.ParseText(code);
var root = tree.GetCompilationUnitRoot();
// 查找 IOADbContext 接口声明
var interfaceDeclaration = root.DescendantNodes().OfType<InterfaceDeclarationSyntax>()
.FirstOrDefault(i => i.Identifier.ValueText == interfaceName);
if (interfaceDeclaration == null) return;
// 解析要添加的属性代码
var newProperty = CSharpSyntaxTree.ParseText(addCode).GetCompilationUnitRoot()
.DescendantNodes().OfType<PropertyDeclarationSyntax>().FirstOrDefault();
if (newProperty == null) return;
// 在接口成员中添加新属性
var newMembers = interfaceDeclaration.Members.Add(newProperty);
var newInterface = interfaceDeclaration.WithMembers(newMembers);
// 替换原接口声明为新接口声明
var newRoot = root.ReplaceNode(interfaceDeclaration, newInterface);
// 获取更新后的代码文本
var newCode = newRoot.GetText().ToString();
// 将更新后的代码写回文件
File.WriteAllText(filePath, newCode);
}
catch (Exception ex)
{
throw new UserFriendlyException($"发生错误AddCodeToInterface: {ex.Message}");
}
}
public static void AddUsing(string filePath, string addCode)
{
try
{
// 读取文件内容
var code = File.ReadAllText(filePath);
// 在第一行添加代码
var newSourceText = SourceText.From(addCode + Environment.NewLine + code);
// 将修改后的内容写回文件
File.WriteAllText(filePath, newSourceText.ToString());
}
catch (Exception ex)
{
throw new UserFriendlyException($"发生错误AddUsing: {ex.Message}");
}
}
public static bool IsExistCode(string filePath, string code)
{
var content = File.ReadAllText(filePath).Replace(" ", "");
return content.Contains(code.Replace(" ","").Replace("\r\n",""));
}
}

77
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Utils/DirectoryAndFileHelper.cs → aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Utils/DirectoryHelper.cs

@ -1,6 +1,6 @@
namespace Lion.AbpPro.Cli.Utils;
public static class DirectoryAndFileHelper
public static class DirectoryHelper
{
/// <summary>
/// 复制文件夹及文件
@ -95,4 +95,79 @@ public static class DirectoryAndFileHelper
throw new UserFriendlyException("删除文件失败!");
}
}
/// <summary>
/// 获取指定路径下所有扩展名为 .sln 的文件
/// </summary>
public static List<string> GetSolutionFiles(string path)
{
var solutionFiles = new List<string>();
var files = Directory.GetFiles(path, "*.sln", SearchOption.AllDirectories);
solutionFiles.AddRange(files);
return solutionFiles;
}
public static void IsAbpProjectStructure(string path, string companyName, string projectName)
{
var dir = Directory.GetDirectories(path);
if (
// 判断是否有Application
dir.Any(e => Path.GetFileName(e) == $"{companyName}.{projectName}.Application") &&
// 判断是否有Application.Contracts
dir.Any(e => Path.GetFileName(e) == $"{companyName}.{projectName}.Application.Contracts") &&
// 判断是否有Domain
dir.Any(e => Path.GetFileName(e) == $"{companyName}.{projectName}.Domain") &&
// 判断是否有Domain.Shared
dir.Any(e => Path.GetFileName(e) == $"{companyName}.{projectName}.Domain.Shared") &&
// 判断是否有EntityFrameworkCore
dir.Any(e => Path.GetFileName(e) == $"{companyName}.{projectName}.EntityFrameworkCore") &&
// 判断是否有HttpApi
dir.Any(e => Path.GetFileName(e) == $"{companyName}.{projectName}.HttpApi") &&
// 判断是否有HttpApi.Client
dir.Any(e => Path.GetFileName(e) == $"{companyName}.{projectName}.HttpApi.Client")
)
{
return;
}
else
{
throw new UserFriendlyException($"请确认项目路径下的项目是否是abp标准结构:{path}");
}
}
public static void IsVben5ProjectStructure(string path)
{
var dir = Directory.GetDirectories(path);
if (
// 判断是否有Application
dir.Any(e => Path.GetFileName(e) == $"router") &&
// 判断是否有Application.Contracts
dir.Any(e => Path.GetFileName(e) == $"views")
)
{
return;
}
else
{
throw new UserFriendlyException($"请确认项目路径下的项目是否是vben5标准结构:{path}");
}
}
private static bool CheckFolder(string path, string name)
{
var dir = Directory.GetDirectories(path);
// 检查路径是否指向一个文件夹
if (Directory.Exists(path))
{
// 获取文件夹名
var folderName = Path.GetFileName(path);
// 判断文件夹名是否以 'Application' 结尾
return folderName.EndsWith(name, StringComparison.OrdinalIgnoreCase);
}
return false;
}
}

2
aspnet-core/frameworks/src/Lion.AbpPro.Cli.Core/Lion/AbpPro/Cli/Utils/ZipHelper.cs

@ -40,7 +40,7 @@ public static class ZipHelper
if (Directory.Exists(targetPath))
{
DirectoryAndFileHelper.DeletedDir(targetPath);
DirectoryHelper.DeletedDir(targetPath);
}
System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, targetPath, Encoding.UTF8, true);

2
aspnet-core/services/src/Lion.AbpPro.Domain/AbpProConsts.cs → aspnet-core/services/src/Lion.AbpPro.Domain/AbpProDbProperties.cs

@ -1,6 +1,6 @@
namespace Lion.AbpPro
{
public static class AbpProConsts
public static class AbpProDbProperties
{
public const string DbTablePrefix = "App";

12
aspnet-core/services/src/Lion.AbpPro.EntityFrameworkCore/EntityFrameworkCore/AbpProDbContext.cs

@ -7,15 +7,6 @@ using Lion.AbpPro.LanguageManagement.LanguageTexts.Aggregates;
using Lion.AbpPro.NotificationManagement.Notifications.Aggregates;
namespace Lion.AbpPro.EntityFrameworkCore
{
/* This is your actual DbContext used on runtime.
* It includes only your entities.
* It does not include entities of the used modules, because each module has already
* its own DbContext class. If you want to share some database tables with the used modules,
* just create a structure like done for AppUser.
*
* Don't use this DbContext for database migrations since it does not contain tables of the
* used modules (as explained above). See AbpProMigrationsDbContext for migrations.
*/
[ConnectionStringName("Default")]
public class AbpProDbContext : AbpDbContext<AbpProDbContext>, IAbpProDbContext,
IBasicManagementDbContext,
@ -87,8 +78,5 @@ namespace Lion.AbpPro.EntityFrameworkCore
// 文件模块
builder.ConfigureFileManagement();
}
}
}

22
aspnet-core/services/src/Lion.AbpPro.EntityFrameworkCore/EntityFrameworkCore/AbpProDbContextModelCreatingExtensions.cs

@ -1,19 +1,11 @@
namespace Lion.AbpPro.EntityFrameworkCore
{
public static class AbpProDbContextModelCreatingExtensions
{
public static void ConfigureAbpPro(this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
using Volo.Abp.EntityFrameworkCore.Modeling;
/* Configure your own tables/entities inside here */
namespace Lion.AbpPro.EntityFrameworkCore;
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable(AbpProConsts.DbTablePrefix + "YourEntities", AbpProConsts.DbSchema);
// b.ConfigureByConvention(); //auto configure for the base class props
// //...
//});
}
public static class AbpProDbContextModelCreatingExtensions
{
public static void ConfigureAbpPro(this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
}
}

4
templates/pro-nuget/service/src/MyCompanyName.MyProjectName.Domain/MyProjectNameConsts.cs → templates/pro-nuget/service/src/MyCompanyName.MyProjectName.Domain/MyProjectNameProperties.cs

@ -1,8 +1,8 @@
namespace MyCompanyName.MyProjectName
{
public static class MyProjectNameConsts
public static class MyProjectNameProperties
{
public const string DbTablePrefix = "App";
public const string DbTablePrefix = "Abp";
public const string DbSchema = null;
}

9
templates/pro-nuget/service/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameDbContext.cs

@ -1,14 +1,5 @@
namespace MyCompanyName.MyProjectName.EntityFrameworkCore
{
/* This is your actual DbContext used on runtime.
* It includes only your entities.
* It does not include entities of the used modules, because each module has already
* its own DbContext class. If you want to share some database tables with the used modules,
* just create a structure like done for AppUser.
*
* Don't use this DbContext for database migrations since it does not contain tables of the
* used modules (as explained above). See MyProjectNameMigrationsDbContext for migrations.
*/
[ConnectionStringName("Default")]
public class MyProjectNameDbContext : AbpDbContext<MyProjectNameDbContext>, IMyProjectNameDbContext,
IBasicManagementDbContext,

22
templates/pro-nuget/service/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameDbContextModelCreatingExtensions.cs

@ -1,19 +1,11 @@
namespace MyCompanyName.MyProjectName.EntityFrameworkCore
{
public static class MyProjectNameDbContextModelCreatingExtensions
{
public static void ConfigureMyProjectName(this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
using Volo.Abp.EntityFrameworkCore.Modeling;
/* Configure your own tables/entities inside here */
namespace MyCompanyName.MyProjectName.EntityFrameworkCore;
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable(MyProjectNameConsts.DbTablePrefix + "YourEntities", MyProjectNameConsts.DbSchema);
// b.ConfigureByConvention(); //auto configure for the base class props
// //...
//});
}
public static class MyProjectNameDbContextModelCreatingExtensions
{
public static void ConfigureMyProjectName(this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
}
}
Loading…
Cancel
Save