我想用ASP.NET Core 2.1创建一个Web服务,该服务在应用程序启动时检查与数据库的连接是否有效,然后在数据库中准备一些数据。
检查将循环运行,直到连接成功或用户按Ctrl + C(IApplicationLifetime
)。在初始化数据库之前,请勿处理任何HTTP调用,这一点很重要。我的问题是:将此代码放在哪里?
我需要对依赖项注入系统进行完全初始化,因此我可以想到的最早是在我的Startup.Configure
方法的末尾,但是IApplicationLifetime
上的取消标记似乎并没有在那儿工作(正确的原因是asp尚未完全启动)
在官方场所可以放置启动逻辑吗?
答案 0 :(得分:2)
您可以基于IWebHost
构建扩展方法,该方法将允许您在Startup.cs
之前运行代码。此外,您可以使用ServiceScopeFactory
来初始化您拥有的任何服务(例如DbContext
)。
public static IWebHost CheckDatabase(this IWebHost webHost)
{
var serviceScopeFactory = (IServiceScopeFactory)webHost.Services.GetService(typeof(IServiceScopeFactory));
using (var scope = serviceScopeFactory.CreateScope())
{
var services = scope.ServiceProvider;
var dbContext = services.GetRequiredService<YourDbContext>();
while(true)
{
if(dbContext.Database.Exists())
{
break;
}
}
}
return webHost;
}
然后您可以使用该方法。
public static void Main(string[] args)
{
BuildWebHost(args)
.CheckDatabase()
.Run();
}
答案 1 :(得分:0)
将此代码放在哪里?
class Initializer
{
internal static SemaphoreSlim _semaphoreSlim;
static SemaphoreSlim Slim
{
get
{
return LazyInitializer.EnsureInitialized(ref _semaphoreSlim, () => new SemaphoreSlim(1, 1));
}
}
public static void WaitOnAction(Action initializer)
{
Initializer.Slim.Wait();
initializer();
Initializer.Slim.Release();
}
}
在哪里可以放置启动逻辑?
Startup.cs是开始的好地方...
Initializer.WaitOnAction(()=> /* ensure db is initialized here */);
/* check https://dotnetfiddle.net/gfTyTL */
答案 2 :(得分:0)
我想使用ASP.NET Core 2.1创建一个可检查应用程序启动的Web服务
例如,我有一个方案来检查文件夹结构,如果不在应用程序启动时立即创建文件夹结构。
用于创建文件夹结构的方法位于 FileService.cs 中,该应用程序必须在启动任何http请求之前启动应用程序,才通过DI来启动。 appsettings.json 包含包含用于创建文件夹结构的结构的键和值。
"FolderStructure": {
"Download": {
"English": {
"*": "*"
},
"Hindi": {
"*": "*"
}
},
"Upload": {
"*": "*"
}
}
并在下面的界面和服务中使用
界面
namespace MyApp.Services
{
public interface IFileService
{
void CreateDirectoryStructure(string path = "");
void CreateFolder(string name, string path = "");
void CreateFile(string name, string path = "");
bool CheckFileExists(string path);
bool CheckFolderExists(string path);
}
}
服务
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Configuration.Binder;
using System.IO;
using Microsoft.Extensions.Logging;
namespace MyApp.Services
{
public class FileService : IFileService
{
private readonly IFileProvider _fileProvider;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IConfiguration _config;
private readonly ILogger<FileService> _logger;
string defaultfolderPath = ConfigurationManager.AppSetting["DefaultDrivePath"];
public FileService(IFileProvider fileProvider, IHostingEnvironment hostingEnvironment, IConfiguration config, ILogger<FileService> logger)
{
_fileProvider = fileProvider;
_hostingEnvironment = hostingEnvironment;
_config = config;
_logger = logger;
}
public void CreateDirectoryStructure(string drivePath = "")
{
if (drivePath.Equals(""))
{
drivePath = ConfigurationManager.AppSetting["DefaultDrivePath"];
_logger.LogInformation($"Default folder path will be picked {drivePath}");
}
foreach (var item in _config.GetSection("FolderStructure").GetChildren())
{
CreateFolder(item.Key, drivePath);
foreach (var i in _config.GetSection(item.Path).GetChildren())
{
if (i.Key != "*")
CreateFolder(i.Key, $"{drivePath}/{item.Key}");
}
}
}
public void CreateFolder(string name, string path = "")
{
string fullPath = string.IsNullOrEmpty(path) ? $"{defaultfolderPath}/{name}" : $"{path}/{name}";
if (!Directory.Exists(fullPath))
{
Directory.CreateDirectory(fullPath);
_logger.LogInformation($"Directory created at {fullPath} on {DateTime.Now}");
}
}
public void CreateFile(string name, string path = "")
{
string fullPath = string.IsNullOrEmpty(path) ? $"{defaultfolderPath}/{name}" : $"{path}/{name}";
if (!File.Exists(fullPath))
{
File.Create(fullPath);
_logger.LogInformation($"File created at {fullPath} on {DateTime.Now}");
}
}
public bool CheckFolderExists(string path)
{
string fullPath = string.IsNullOrEmpty(path) ? defaultfolderPath : path;
return Directory.Exists(fullPath);
}
public bool CheckFileExists(string path)
{
string fullPath = string.IsNullOrEmpty(path) ? defaultfolderPath : path;
return File.Exists(fullPath);
}
}
}
现在的挑战是在应用程序启动后立即调用文件夹服务方法,但我们需要通过DI初始化文件服务
services.AddSingleton<IFileService, FileService>();
然后在Configure方法中,您可以调用所需的服务。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IFileService FileService)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
//dont change the below order as middleware exception need to be registered before UseMvc method register
app.ConfigureCustomMiddleware();
// app.UseHttpsRedirection();
app.UseMvc();
FileService.CreateDirectoryStructure();
}