diff --git a/BootstrapAdmin.sln b/BootstrapAdmin.sln index 11a708d1..3e928488 100644 --- a/BootstrapAdmin.sln +++ b/BootstrapAdmin.sln @@ -33,6 +33,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MongoDB", "MongoDB", "{A06A db\MongoDB\Dicts.js = db\MongoDB\Dicts.js db\MongoDB\Groups.js = db\MongoDB\Groups.js db\MongoDB\init.js = db\MongoDB\init.js + db\MongoDB\install.cmd = db\MongoDB\install.cmd db\MongoDB\install.sh = db\MongoDB\install.sh db\MongoDB\Navigations.js = db\MongoDB\Navigations.js db\MongoDB\Roles.js = db\MongoDB\Roles.js diff --git a/db/MongoDB/install.cmd b/db/MongoDB/install.cmd new file mode 100644 index 00000000..e5f8ef0b --- /dev/null +++ b/db/MongoDB/install.cmd @@ -0,0 +1,5 @@ +# init mongodb data +@echo off + +mongo ./init.js +mongo BootstrapAdmin --eval "printjson(db.getCollectionNames())" diff --git a/db/SqlServer/install.ps1 b/db/SqlServer/install.ps1 index 78b0b25b..22b7246f 100644 --- a/db/SqlServer/install.ps1 +++ b/db/SqlServer/install.ps1 @@ -1,5 +1,9 @@ # init sqlserver database -$startPath = "Z:\src\Longbow\BootstrapAdmin\DatabaseScripts\SqlServer" +$startPath = $args[0] +if ($startPath -eq $null) { + $startPath = "Z:\src\Longbow\BootstrapAdmin\db\SqlServer" +} + $sqlInstance = "localhost" $outFile = join-path $startPath "output.log" $sqlFile = join-path $startPath "Install.sql" diff --git a/src/admin/Bootstrap.Admin/AutoGenerateDatabaseExtensions.cs b/src/admin/Bootstrap.Admin/AutoGenerateDatabaseExtensions.cs new file mode 100644 index 00000000..09de0b2d --- /dev/null +++ b/src/admin/Bootstrap.Admin/AutoGenerateDatabaseExtensions.cs @@ -0,0 +1,64 @@ +using Bootstrap.DataAccess.Helper; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System.IO; +using System.Linq; +using System; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// 自动生成数据库扩展操作类 + /// + public static class AutoGenerateDatabaseExtensions + { + private static bool _init; + private static object _locker = new object(); + + /// + /// 自动生成数据库中间件 + /// + /// + public static IApplicationBuilder UseAutoGenerateDatabase(this IApplicationBuilder app) + { + app.Use(async (context, next) => + { + if (!_init) + { + // 阻止所有线程继续往下运行,等待数据库检查 + lock (_locker) + { + if (!_init) + { + // 数据检查 + var config = context.RequestServices.GetRequiredService(); + var dbSection = config.GetSection("DB").GetChildren().FirstOrDefault(c => c.GetValue("Enabled", false)); + if (dbSection != null) + { + var folder = dbSection["SqlFolder"].ReplaceOSPlatformPath(); + if (!string.IsNullOrEmpty(folder)) + { + // 判断文件夹是否存在 + var env = context.RequestServices.GetRequiredService(); + var fullFolder = Path.Combine(env.ContentRootPath, folder); + if (Directory.Exists(fullFolder)) + { + try + { + AutoDbHelper.CheckDB(fullFolder); + } + catch { } + } + } + } + } + _init = true; + } + } + await next(); + }); + return app; + } + } +} diff --git a/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj b/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj index 841aa89a..a00ac7b0 100644 --- a/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj +++ b/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj @@ -13,16 +13,19 @@ + + - + + diff --git a/src/admin/Bootstrap.Admin/Properties/launchSettings.json b/src/admin/Bootstrap.Admin/Properties/launchSettings.json index 818a0181..7d62f9f0 100644 --- a/src/admin/Bootstrap.Admin/Properties/launchSettings.json +++ b/src/admin/Bootstrap.Admin/Properties/launchSettings.json @@ -16,6 +16,11 @@ "ASPNETCORE_ENVIRONMENT": "Development" } }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}" + }, "Bootstrap.Admin": { "commandName": "Project", "launchBrowser": true, @@ -23,11 +28,6 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "http://localhost:50852/" - }, - "Docker": { - "commandName": "Docker", - "launchBrowser": true, - "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}" } } } \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Startup.cs b/src/admin/Bootstrap.Admin/Startup.cs index ce258b32..05ed94a3 100644 --- a/src/admin/Bootstrap.Admin/Startup.cs +++ b/src/admin/Bootstrap.Admin/Startup.cs @@ -115,6 +115,7 @@ namespace Bootstrap.Admin app.UseHttpsRedirection(); app.UseResponseCompression(); app.UseStaticFiles(); + app.UseAutoGenerateDatabase(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); diff --git a/src/admin/Bootstrap.Admin/appsettings.Development.json b/src/admin/Bootstrap.Admin/appsettings.Development.json index 0ebdc609..9cd8411c 100644 --- a/src/admin/Bootstrap.Admin/appsettings.Development.json +++ b/src/admin/Bootstrap.Admin/appsettings.Development.json @@ -19,6 +19,7 @@ { "Enabled": false, "ProviderName": "SqlServer", + "SqlFolder": "..\\..\\..\\db\\SqlServer", "ConnectionStrings": { "ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa" } @@ -26,6 +27,7 @@ { "Enabled": true, "ProviderName": "Sqlite", + "SqlFolder": "..\\..\\..\\db\\SQLite", "ConnectionStrings": { "ba": "Data Source=BootstrapAdmin.db;" } @@ -33,6 +35,7 @@ { "Enabled": false, "ProviderName": "MySql", + "SqlFolder": "..\\..\\..\\db\\MySQL", "ConnectionStrings": { "ba": "Server=localhost;Database=BA;Uid=argozhang;Pwd=argo@163.com;SslMode=none;" } @@ -48,6 +51,7 @@ "Enabled": false, "Widget": "Bootstrap.DataAccess.MongoDB", "ProviderName": "MongoDB", + "SqlFolder": "..\\..\\..\\db\\MongoDB", "ConnectionStrings": { "ba": "mongodb://localhost:27017/BootstrapAdmin" } diff --git a/src/admin/Bootstrap.DataAccess.MongoDB/AutoDB.cs b/src/admin/Bootstrap.DataAccess.MongoDB/AutoDB.cs new file mode 100644 index 00000000..e633392b --- /dev/null +++ b/src/admin/Bootstrap.DataAccess.MongoDB/AutoDB.cs @@ -0,0 +1,17 @@ +namespace Bootstrap.DataAccess.MongoDB +{ + /// + /// 自动建库实体操作类 + /// + public class AutoDB : DataAccess.AutoDB + { + /// + /// 数据库检查方法 + /// + /// + public override void CheckDB(string folder) + { + // UNDONE: 没有环境暂时未写代码 + } + } +} diff --git a/src/admin/Bootstrap.DataAccess/AutoDB.cs b/src/admin/Bootstrap.DataAccess/AutoDB.cs new file mode 100644 index 00000000..a1992a60 --- /dev/null +++ b/src/admin/Bootstrap.DataAccess/AutoDB.cs @@ -0,0 +1,94 @@ +using PetaPoco; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; + +namespace Bootstrap.DataAccess +{ + /// + /// 数据库自动生成实体类 + /// + public class AutoDB + { + private string _folder; + + /// + /// 数据库检查方法 + /// + public virtual void CheckDB(string folder) + { + _folder = folder; + using (var db = Longbow.Data.DbManager.Create()) + { + db.CommandTimeout = 5000; + switch (db.Provider.GetType().Name) + { + case "SQLiteDatabaseProvider": + if (db.ExecuteScalar("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='Users'") == 0) GenerateSQLiteDB(db); + break; + case "SqlServerDatabaseProvider": + using (var newDB = ModifyConnectionString(db)) + { + if (newDB.ExecuteScalar("select COUNT(1) from sys.databases where name = N'BootstrapAdmin'") == 0) GenerateSqlServer(); + } + break; + case "MySqlDatabaseProvider": + case "MariaDbDatabaseProvider": + // UNDONE: 本地没有环境此处代码未测试 + if (db.ExecuteScalar("select count(*) from information_schema.tables where table_name ='Users' and Table_Schema = 'BootstrapAdmin'") == 0) GenerateMySql(); + break; + } + } + } + + private IDatabase ModifyConnectionString(IDatabase db) + { + var conn = db.ConnectionString; + var newsegs = new List(); + var segs = conn.SpanSplit(";"); + segs.ForEach(s => + { + if (s.StartsWith("Initial Catalog", StringComparison.OrdinalIgnoreCase)) newsegs.Add("Initial Catalog=master"); + else newsegs.Add(s); + }); + var provider = db.Provider; + return new Database(string.Join(";", newsegs), provider); + } + + private void GenerateSQLiteDB(IDatabase db) + { + var folder = _folder; + var initFile = Path.Combine(folder, "Install.sql"); + if (File.Exists(initFile)) + { + var sql = File.ReadAllText(initFile); + db.Execute(sql); + + initFile = Path.Combine(folder, "InitData.sql"); + if (File.Exists(initFile)) + { + sql = File.ReadAllText(initFile); + db.Execute(sql); + } + } + } + + private void GenerateSqlServer() + { + // 检查 install.ps1 脚本 + var file = Path.Combine(_folder, $"install.ps1"); + if (File.Exists(file)) + { + var psi = new ProcessStartInfo("powershell", $"{file} \"{_folder}\""); + var p = Process.Start(psi); + p.WaitForExit(); + } + } + + private void GenerateMySql() + { + // UNDONE: 没有环境暂时未写代码 + } + } +} diff --git a/src/admin/Bootstrap.DataAccess/Helper/AutoDbHelper.cs b/src/admin/Bootstrap.DataAccess/Helper/AutoDbHelper.cs new file mode 100644 index 00000000..f99416db --- /dev/null +++ b/src/admin/Bootstrap.DataAccess/Helper/AutoDbHelper.cs @@ -0,0 +1,13 @@ +namespace Bootstrap.DataAccess.Helper +{ + /// + /// 数据库自动生成帮助类 + /// + public static class AutoDbHelper + { + /// + /// 数据库检查方法 + /// + public static void CheckDB(string folder) => DbContextManager.Create()?.CheckDB(folder); + } +}