From acebe33cad0664a4b0532fc4cc08698700098208 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 1 Oct 2019 22:50:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(#I12XDG):=20=E8=87=AA=E5=8A=A8=E5=BB=BA?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #Comment comment #I12XDG #Issue link #I12XDG --- db/SqlServer/install.ps1 | 6 +- .../AutoGenerateDatabaseExtensions.cs | 24 ++++ .../Bootstrap.Admin/Bootstrap.Admin.csproj | 1 + src/admin/Bootstrap.Admin/Startup.cs | 1 + .../appsettings.Development.json | 4 + src/admin/Bootstrap.DataAccess/AutoDB.cs | 114 ++++++++++++++++++ .../Helper/AutoDbHelper.cs | 13 ++ 7 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/admin/Bootstrap.Admin/AutoGenerateDatabaseExtensions.cs create mode 100644 src/admin/Bootstrap.DataAccess/AutoDB.cs create mode 100644 src/admin/Bootstrap.DataAccess/Helper/AutoDbHelper.cs 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..bca33660 --- /dev/null +++ b/src/admin/Bootstrap.Admin/AutoGenerateDatabaseExtensions.cs @@ -0,0 +1,24 @@ +using Bootstrap.DataAccess.Helper; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// 自动生成数据库扩展操作类 + /// + public static class AutoGenerateDatabaseExtensions + { + /// + /// 自动生成数据库中间件 + /// + /// + public static IApplicationBuilder UseAutoGenerateDatabase(this IApplicationBuilder app) + { + app.Use(async (context, next) => + { + AutoDbHelper.CheckDB(); + await next(); + }); + return app; + } + } +} diff --git a/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj b/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj index 841aa89a..f85dbc62 100644 --- a/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj +++ b/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj @@ -23,6 +23,7 @@ + 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..fd88f310 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": "Z:\\src\\Longbow\\BootstrapAdmin\\db\\SqlServer", "ConnectionStrings": { "ba": "Data Source=.;Initial Catalog=BootstrapAdmin;User ID=sa;Password=sa" } @@ -26,6 +27,7 @@ { "Enabled": true, "ProviderName": "Sqlite", + "SqlFolder": "Z:\\src\\Longbow\\BootstrapAdmin\\db\\SQLite", "ConnectionStrings": { "ba": "Data Source=BootstrapAdmin.db;" } @@ -33,6 +35,7 @@ { "Enabled": false, "ProviderName": "MySql", + "SqlFolder": "Z:\\src\\Longbow\\BootstrapAdmin\\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": "Z:\\src\\Longbow\\BootstrapAdmin\\db\\MongoDB", "ConnectionStrings": { "ba": "mongodb://localhost:27017/BootstrapAdmin" } diff --git a/src/admin/Bootstrap.DataAccess/AutoDB.cs b/src/admin/Bootstrap.DataAccess/AutoDB.cs new file mode 100644 index 00000000..a2d82097 --- /dev/null +++ b/src/admin/Bootstrap.DataAccess/AutoDB.cs @@ -0,0 +1,114 @@ +using Longbow.Configuration; +using Microsoft.Extensions.Configuration; +using PetaPoco; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace Bootstrap.DataAccess +{ + /// + /// 数据库自动生成实体类 + /// + public class AutoDB + { + private static bool _init = false; + private static object _locker = new object(); + + /// + /// 数据库检查方法 + /// + public void CheckDB() + { + if (_init) return; + + // 阻止所有线程继续往下运行,等待数据库检查 + lock (_locker) + { + if (_init) return; + + // 数据检查 + Check(); + } + } + + private void Check() + { + var dbSection = ConfigurationManager.GetSection("DB").GetChildren().FirstOrDefault(c => c.GetValue("Enabled", false)); + if (dbSection == null) + { + _init = true; + return; + } + var folder = dbSection["SqlFolder"]; + if (folder.IsNullOrEmpty()) + { + _init = true; + return; + } + + var db = Longbow.Data.DbManager.Create(); + CheckDbExists(db, folder); + _init = true; + } + + private void CheckDbExists(IDatabase db, string folder) + { + 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, folder); + break; + case "SqlServerDatabaseProvider": + var newDB = ModifyConnectionString(db); + if (newDB.ExecuteScalar("select COUNT(1) from sys.databases where name = N'BootstrapAdmin'") == 0) GenerateSqlServer(folder); + break; + case "MySqlDatabaseProvider": + case "MariaDbDatabaseProvider": + if (db.ExecuteScalar("select count(*) from information_schema.tables where table_name ='Users' and Table_Schema = 'BootstrapAdmin'") == 0) GenerateMySql(folder); + 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; + db.Dispose(); + return new Database(string.Join(";", newsegs), provider); + } + + private void GenerateSQLiteDB(IDatabase db, string folder) + { + var initFile = Path.Combine(folder, "Install.sql"); + var sql = File.ReadAllText(initFile); + db.Execute(sql); + + initFile = Path.Combine(folder, "InitData.sql"); + sql = File.ReadAllText(initFile); + db.Execute(sql); + } + + private void GenerateSqlServer(string folder) + { + var psi = new ProcessStartInfo("powershell", Path.Combine(folder, $"install.ps1 \"{folder}\"")); + var p = Process.Start(psi); + p.WaitForExit(); + } + + private void GenerateMySql(string folder) + { + // 没有环境暂时未写代码 + } + } +} diff --git a/src/admin/Bootstrap.DataAccess/Helper/AutoDbHelper.cs b/src/admin/Bootstrap.DataAccess/Helper/AutoDbHelper.cs new file mode 100644 index 00000000..94cf2157 --- /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() => DbContextManager.Create()?.CheckDB(); + } +}