您好,欢迎来到五一七教育网。
搜索
您的当前位置:首页Web开发:ABP框架1——入门级别的Demo下载安装、表创建、数据迁移

Web开发:ABP框架1——入门级别的Demo下载安装、表创建、数据迁移

来源:五一七教育网

一、Demo的安装

1.打开命令行 ,安装ABPCLI

ABPCLI是abp团队开发的一个命令行界面,是安装demo项目的工具,我们在电脑windows图表的左下角搜索cmd,右键管理员身份运行

如果你想安装最新版本,请输入命令:

dotnet tool install -g Volo.Abp.Cli 

如果你想安装指定版本,请输入命令 

dotnet tool install -g Volo.Abp.Cli --version 6.0.0

如果你安装了旧版,想更新到新版,请输入命令:

dotnet tool update -g Volo.Abp.Cli

如果你安装了新版,想换回旧版,先卸后安装,依次输入命令:

dotnet tool uninstall -g Volo.Abp.Cli
dotnet tool install -g Volo.Abp.Cli --version 6.0.0

注意:本来我装的是最新的8.3.0版本,结果数据迁移的时候生成的SQL报错了,暂时没办法排除,于是后面又用回了6.0.0版本,悉知! 

2.切换到工作目录,安装项目

MVC可以输入:

abp new Acme.BookStore -t app -u mvc --mobile none --database-provider ef -csf

Webapi可以输入:

abp new Acme.BookStore -u none --separate-auth-server -csf

如果指定版本(我就是用下面这个命令的):

abp new Acme.BookStore -u none --separate-auth-server -csf -version 6.0.0

 更多命令,请访问官网。

【可能的报错】

Q1:如果你的版本太低,请尝试这样安装项目:

xxxxx --version 6.0.0

1.禁用 npm 对 SSL 证书的严格检查

npm config set strict-ssl false

2.清缓存

npm cache clean --force

3.切换镜像源

npm config set registry https://registry.npm.taobao.org/

 Q3:缺少依赖库

这个补充相应的依赖库即可,例如我的报错:

红色字体的部分,每个人都不一样,请观察自己的命令行提示缺哪个补哪个

3.成功安装的解决方案目录

        后续内容将演示SQLsever+EFcore+Webapi +.NET 6.0的demo

二、实体的准备

按照官网的步骤来:

1.新建一个Book实体

类库代码用途
Acme.BookStore.Domain.Shared

namespace Acme.BookStore.Books
{
    public enum BookType
    {
        Undefined,
        Adventure,
        Biography,
        Dystopia,
        Fantastic,
        Horror,
        Science,
        ScienceFiction,
        Poetry
    }
}

新建枚举
Acme.BookStore.Domain

using System;
using Volo.Abp.Domain.Entities.Auditing;

namespace Acme.BookStore.Books
{
    public class Book : AuditedAggregateRoot<Guid>
    {
        public string Name { get; set; }

        public BookType Type { get; set; }

        public DateTime PublishDate { get; set; }

        public float Price { get; set; }
    }
}

新建实体

2.将实体加入到EFcore的上下文类

目的:用EFcore这个ORM框架查表

增加位置:(注意看连接字符串用的是Default)

DbContext=>DbContextModelCreatingExtensions 

下图箭头开始位置标错了,应该是此方法里面的builder.OnModelCreating()方法跳转到右边

增加内容:

代码
Dbsetpublic class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
{
    public DbSet<Book> Books { get; set; }
    //...
}
 
builder.Entitybuilder.Entity<Book>(b =>
{
       b.ToTable(BookStoreConsts.DbTablePrefix + "Books",BookStoreConsts.DbSchema);
      b.ConfigureByConvention(); //auto configure for the base class props
      b.Property(x => x.Name).IsRequired().HasMaxLength(128);
 });

三、基于EFcore的表的生成和数据迁移 

1.使用EFcore的命令新建数据表

.\src\Acme.BookStore.DbMigrator\appsettings.json

.\src\Acme.BookStore.Web\appsettings.json

连接字符串改为(当然,你可以自己起名):

Server=localhost; Database=TestABP;Trusted_Connection=True;TrustServerCertificate=true

就像这样: 

 然后找到程序包管理器并且打开它

选择EFcore类库 

 找到EFcore这个类库,右键设为启动项目,再输入下面两句命令:

Add-Migration Created_Book_Entity -c BookStoreDbContext
Update-Database -Context BookStoreDbContext

如果控制台窗口没有报错,看看我们的EFcore类库下是否多了下面这个生成的迁移文件:

然后去我们的SQLserver看看,发现已经生成了数据表!

【注意】EFcore成功新建数据表需要做到以下几点

1.必须设为启动项目,再在程序包管理程序输入命令

2.必须是编译通过的程序,才能成功执行上述命令

3.必须是连接字符串正确,才能成功执行上述命令

2.各表的含义

(我是问AI的,如有不对,敬请指出)

表名含义字段
__EFMigrationsHistoryEfcore迁移历史记录表MigrationId,ProductVersion
AbpAuditLogs审计日志表(用户操作记录表)Id,ApplicationName,UserId,UserName,TenantId,TenantName,ImpersonatorUserId,ImpersonatorUserName,ImpersonatorTenantId,ImpersonatorTenantName,ExecutionTime,ExecutionDuration,ClientIpAddress,ClientName,ClientId,CorrelationId,BrowserInfo,HttpMethod,Url,Exceptions,Comments,HttpStatusCode,ExtraProperties,ConcurrencyStamp
AbpBackgroundJobs后台作业表Id,JobName,JobArgs,TryCount,CreationTime,NextTryTime,LastTryTime,IsAbandoned,Priority,ExtraProperties,ConcurrencyStamp
AbpClaimTypes用户声明类型表Id,Name,Required,IsStatic,Regex,RegexDescription,Description,ValueType,ExtraProperties,ConcurrencyStamp
AbpFeatureGroups组织管理表Id,Name,DisplayName,ExtraProperties
AbpFeatures功能设置表Id,GroupName,Name,ParentName,DisplayName,Description,DefaultValue,IsVisibleToClients,IsAvailableToHost,AllowedProviders,ValueType,ExtraProperties
AbpFeatureValues功能值表Id,Name,Value,ProviderName,ProviderKey
AbpLinkUsers用户关联表Id,SourceUserId,SourceTenantId,TargetUserId,TargetTenantId
AbpOrganizationUnits组织单元表Id,TenantId,ParentId,Code,DisplayName,EntityVersion,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime
AbpPermissionGrants角色权限表Id,TenantId,Name,ProviderName,ProviderKey
AbpPermissionGroups组权限表Id,Name,DisplayName,ExtraProperties
AbpPermissions权限定义表Id,GroupName,Name,ParentName,DisplayName,IsEnabled,MultiTenancySide,Providers,StateCheckers,ExtraProperties
AbpRoles角色信息表Id,TenantId,Name,NormalizedName,IsDefault,IsStatic,IsPublic,EntityVersion,ExtraProperties,ConcurrencyStamp
AbpSecurityLogs安全日志表(登录日志)Id,TenantId,ApplicationName,Identity,Action,UserId,UserName,TenantName,ClientId,CorrelationId,ClientIpAddress,BrowserInfo,CreationTime,ExtraProperties,ConcurrencyStamp
AbpSessions用户登录会话表Id,SessionId,Device,DeviceInfo,TenantId,UserId,ClientId,IpAddresses,SignedIn,LastAccessed
AbpSettingDefinitions系统设置定义表Id,Name,DisplayName,Description,DefaultValue,IsVisibleToClients,Providers,IsInherited,IsEncrypted,ExtraProperties
AbpSettings系统设置表Id,Name,Value,ProviderName,ProviderKey
AbpTenants租户信息表Id,Name,NormalizedName,EntityVersion,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime
AbpUserDelegations用户委托表Id,TenantId,SourceUserId,TargetUserId,StartTime,EndTime
AbpUsers用户表Id,TenantId,UserName,NormalizedUserName,Name,Surname,Email,NormalizedEmail,EmailConfirmed,PasswordHash,SecurityStamp,IsExternal,PhoneNumber,PhoneNumberConfirmed,IsActive,TwoFactorEnabled,LockoutEnd,LockoutEnabled,AccessFailedCount,ShouldChangePasswordOnNextLogin,EntityVersion,LastPasswordChangeTime,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime
OpenIddictApplications客户端应用表Id,ApplicationType,ClientId,ClientSecret,ClientType,ConsentType,DisplayName,DisplayNames,JsonWebKeySet,Permissions,PostLogoutRedirectUris,Properties,RedirectUris,Requirements,Settings,ClientUri,LogoUri,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime
OpenIddictScopes客户端可访问资源表Id,Description,Descriptions,DisplayName,DisplayNames,Name,Properties,Resources,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime
AbpAuditLogActions审计细节表Id,TenantId,AuditLogId,ServiceName,MethodName,Parameters,ExecutionTime,ExecutionDuration,ExtraProperties
AbpEntityChanges实体变化表Id,AuditLogId,TenantId,ChangeTime,ChangeType,EntityTenantId,EntityId,EntityTypeFullName,ExtraProperties
AbpOrganizationUnitRoles组织角色关联表RoleId,OrganizationUnitId,TenantId,CreationTime,CreatorId
AbpRoleClaims角色声明表Id,RoleId,TenantId,ClaimType,ClaimValue
AbpTenantConnectionStrings租户连接字符串表TenantId,Name,Value
AbpUserClaims用户声明表Id,UserId,TenantId,ClaimType,ClaimValue
AbpUserLogins用户登录表UserId,LoginProvider,TenantId,ProviderKey,ProviderDisplayName
AbpUserOrganizationUnits组织单元关系表UserId,OrganizationUnitId,TenantId,CreationTime,CreatorId
AbpUserRoles用户角色关联表UserId,RoleId,TenantId
AbpUserTokens用户令牌表UserId,LoginProvider,Name,TenantId,Value
OpenIddictAuthorizations客户端授权表Id,ApplicationId,CreationDate,Properties,Scopes,Status,Subject,Type,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime
AbpEntityPropertyChanges属性变化表Id,TenantId,EntityChangeId,NewValue,OriginalValue,PropertyName,PropertyTypeFullName
OpenIddictTokens客户端令牌验证表Id,ApplicationId,AuthorizationId,CreationDate,ExpirationDate,Payload,Properties,RedemptionDate,ReferenceId,Status,Subject,Type,ExtraProperties,ConcurrencyStamp,CreationTime,CreatorId,LastModificationTime,LastModifierId,IsDeleted,DeleterId,DeletionTime

 3.种子数据的迁移

新建如下文件

代码(官网获取的):

using Acme.BookStore.Books;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;

namespace Acme.BookStore.Seed
{
    public class BookStoreDataSeederContributor
            : IDataSeedContributor, ITransientDependency
    {
        private readonly IRepository<Book, Guid> _bookRepository;

        public BookStoreDataSeederContributor(IRepository<Book, Guid> bookRepository)
        {
            _bookRepository = bookRepository;
        }

        public async Task SeedAsync(DataSeedContext context)
        {
            if (await _bookRepository.GetCountAsync() <= 0)
            {
                await _bookRepository.InsertAsync(
                    new Book
                    {
                        Name = "1984",
                        Type = BookType.Dystopia,
                        PublishDate = new DateTime(1949, 6, 8),
                        Price = 19.84f
                    },
                    autoSave: true
                );

                await _bookRepository.InsertAsync(
                    new Book
                    {
                        Name = "The Hitchhiker's Guide to the Galaxy",
                        Type = BookType.ScienceFiction,
                        PublishDate = new DateTime(1995, 9, 27),
                        Price = 42.0f
                    },
                    autoSave: true
                );
            }
        }
    }
}

【方案一:启动种子数据服务】

.\src\Acme.BookStore.DbMigrator

然后运行项目,去数据库发现已经更新成功!

 【方案二:SQL插入】

反正这个数据迁移用处不是很大,特别是我第一次下了最新版8.3.0,可能没做好居然有bug,它拿生成的SQL去执行结果报错了!

/*
 Navicat Premium Data Transfer

 Source Server         : 本地数据库
 Source Server Type    : SQL Server
 Source Server Version : 11003000
 Source Host           : localhost:1433
 Source Catalog        : TestABP
 Source Schema         : dbo

 Target Server Type    : SQL Server
 Target Server Version : 11003000
 File Encoding         : 65001

 Date: 12/09/2024 22:27:52
*/


-- ----------------------------
-- Table structure for AbpUsers
-- ----------------------------
IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[dbo].[AbpUsers]') AND type IN ('U'))
	DROP TABLE [dbo].[AbpUsers]
GO

CREATE TABLE [dbo].[AbpUsers] (
  [Id] uniqueidentifier  NOT NULL,
  [TenantId] uniqueidentifier  NULL,
  [UserName] nvarchar(256) COLLATE Chinese_PRC_CI_AS  NOT NULL,
  [NormalizedUserName] nvarchar(256) COLLATE Chinese_PRC_CI_AS  NOT NULL,
  [Name] nvarchar() COLLATE Chinese_PRC_CI_AS  NULL,
  [Surname] nvarchar() COLLATE Chinese_PRC_CI_AS  NULL,
  [Email] nvarchar(256) COLLATE Chinese_PRC_CI_AS  NOT NULL,
  [NormalizedEmail] nvarchar(256) COLLATE Chinese_PRC_CI_AS  NOT NULL,
  [EmailConfirmed] bit DEFAULT (CONVERT([bit],(0))) NOT NULL,
  [PasswordHash] nvarchar(256) COLLATE Chinese_PRC_CI_AS  NULL,
  [SecurityStamp] nvarchar(256) COLLATE Chinese_PRC_CI_AS  NOT NULL,
  [IsExternal] bit DEFAULT (CONVERT([bit],(0))) NOT NULL,
  [PhoneNumber] nvarchar(16) COLLATE Chinese_PRC_CI_AS  NULL,
  [PhoneNumberConfirmed] bit DEFAULT (CONVERT([bit],(0))) NOT NULL,
  [IsActive] bit  NOT NULL,
  [TwoFactorEnabled] bit DEFAULT (CONVERT([bit],(0))) NOT NULL,
  [LockoutEnd] datetimeoffset(7)  NULL,
  [LockoutEnabled] bit DEFAULT (CONVERT([bit],(0))) NOT NULL,
  [AccessFailedCount] int DEFAULT ((0)) NOT NULL,
  [ExtraProperties] nvarchar(max) COLLATE Chinese_PRC_CI_AS  NULL,
  [ConcurrencyStamp] nvarchar(40) COLLATE Chinese_PRC_CI_AS  NULL,
  [CreationTime] datetime2(7)  NOT NULL,
  [CreatorId] uniqueidentifier  NULL,
  [LastModificationTime] datetime2(7)  NULL,
  [LastModifierId] uniqueidentifier  NULL,
  [IsDeleted] bit DEFAULT (CONVERT([bit],(0))) NOT NULL,
  [DeleterId] uniqueidentifier  NULL,
  [DeletionTime] datetime2(7)  NULL
)
GO

ALTER TABLE [dbo].[AbpUsers] SET (LOCK_ESCALATION = TABLE)
GO


-- ----------------------------
-- Records of [AbpUsers]
-- ----------------------------
INSERT INTO [dbo].[AbpUsers]  VALUES (N'DDBC879C-006B-A4F2-423F-3A14F8ACA0F3', NULL, N'admin', N'ADMIN', N'admin', NULL, N'admin@abp.io', N'ADMIN@ABP.IO', N'0', N'AQAAAAEAACcQAAAAEEJg+LZ6xWkgZN+8GX2ERTesvO08TeR16oPLwxPzP49ZdkPDvY7LDS/wJvchwDpf5A==', N'74OFRJASEJHS3EPQ2V73NXBMEFENTFCJ', N'0', NULL, N'0', N'1', N'0', NULL, N'1', N'0', N'{}', N'09943ab4d1f343a2ac1a57d421413c7d', N'2024-09-12 21:50:20.1663169', NULL, N'2024-09-12 21:50:21.0595668', NULL, N'0', NULL, NULL)
GO


-- ----------------------------
-- Indexes structure for table AbpUsers
-- ----------------------------
CREATE NONCLUSTERED INDEX [IX_AbpUsers_Email]
ON [dbo].[AbpUsers] (
  [Email] ASC
)
GO

CREATE NONCLUSTERED INDEX [IX_AbpUsers_NormalizedEmail]
ON [dbo].[AbpUsers] (
  [NormalizedEmail] ASC
)
GO

CREATE NONCLUSTERED INDEX [IX_AbpUsers_NormalizedUserName]
ON [dbo].[AbpUsers] (
  [NormalizedUserName] ASC
)
GO

CREATE NONCLUSTERED INDEX [IX_AbpUsers_UserName]
ON [dbo].[AbpUsers] (
  [UserName] ASC
)
GO


-- ----------------------------
-- Primary Key structure for table AbpUsers
-- ----------------------------
ALTER TABLE [dbo].[AbpUsers] ADD CONSTRAINT [PK_AbpUsers] PRIMARY KEY CLUSTERED ([Id])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)  
ON [PRIMARY]
GO

/*
 Navicat Premium Data Transfer

 Source Server         : 本地数据库
 Source Server Type    : SQL Server
 Source Server Version : 11003000
 Source Host           : localhost:1433
 Source Catalog        : TestABP
 Source Schema         : dbo

 Target Server Type    : SQL Server
 Target Server Version : 11003000
 File Encoding         : 65001

 Date: 12/09/2024 22:28:32
*/


-- ----------------------------
-- Table structure for AppBooks
-- ----------------------------
IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[dbo].[AppBooks]') AND type IN ('U'))
	DROP TABLE [dbo].[AppBooks]
GO

CREATE TABLE [dbo].[AppBooks] (
  [Id] uniqueidentifier  NOT NULL,
  [Name] nvarchar(128) COLLATE Chinese_PRC_CI_AS  NOT NULL,
  [Type] int  NOT NULL,
  [PublishDate] datetime2(7)  NOT NULL,
  [Price] real  NOT NULL,
  [ExtraProperties] nvarchar(max) COLLATE Chinese_PRC_CI_AS  NULL,
  [ConcurrencyStamp] nvarchar(40) COLLATE Chinese_PRC_CI_AS  NULL,
  [CreationTime] datetime2(7)  NOT NULL,
  [CreatorId] uniqueidentifier  NULL,
  [LastModificationTime] datetime2(7)  NULL,
  [LastModifierId] uniqueidentifier  NULL
)
GO

ALTER TABLE [dbo].[AppBooks] SET (LOCK_ESCALATION = TABLE)
GO


-- ----------------------------
-- Records of [AppBooks]
-- ----------------------------
INSERT INTO [dbo].[AppBooks]  VALUES (N'DBE0E4C6-92F3-86E6-6883-3A14F8CB22', N'1984', N'3', N'1949-06-08 00:00:00.0000000', N'19.8400002', N'{}', N'b2ade2162b494b73bbb5d992d2958a3a', N'2024-09-12 22:24:05.4579808', NULL, NULL, NULL)
GO

INSERT INTO [dbo].[AppBooks]  VALUES (N'4C8AB716-8757-CC73-1107-3A14F8CB8A74', N'The Hitchhiker''s Guide to the Galaxy', N'7', N'1995-09-27 00:00:00.0000000', N'42.0000000', N'{}', N'fe5db7bee56943f0baea1a1bc22d9054', N'2024-09-12 22:24:05.7487193', NULL, NULL, NULL)
GO


-- ----------------------------
-- Primary Key structure for table AppBooks
-- ----------------------------
ALTER TABLE [dbo].[AppBooks] ADD CONSTRAINT [PK_AppBooks] PRIMARY KEY CLUSTERED ([Id])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)  
ON [PRIMARY]
GO

4.卸载迁移项目

成功迁移数据表后,后面几乎不会用到它了,所以可以【右键-卸载项目】

五、迁移类库代码的解读

【Program.cs】

using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;

namespace Acme.BookStore.DbMigrator
{
    // 定义 Program 类作为应用程序的入口点
    class Program
    {
        // 主方法:应用程序的入口点
        static async Task Main(string[] args)
        {
            // 配置 Serilog 日志记录器
            Log.Logger = new LoggerConfiguration()
                // 设置日志记录器的最低日志级别为 Information
                .MinimumLevel.Information()
                // 将 Microsoft 命名空间的日志级别覆盖为 Warning
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                // 将 Volo.Abp 命名空间的日志级别覆盖为 Warning
                .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning)
                // 在 Debug 模式下,将 Acme.BookStore 命名空间的日志级别设置为 Debug
#if DEBUG
                .MinimumLevel.Override("Acme.BookStore", LogEventLevel.Debug)
#else
                // 在非 Debug 模式下,将 Acme.BookStore 命名空间的日志级别设置为 Information
                .MinimumLevel.Override("Acme.BookStore", LogEventLevel.Information)
#endif
                // 从日志上下文中添加日志信息
                .Enrich.FromLogContext()
                // 异步写入日志到文件 "Logs/logs.txt"
                .WriteTo.Async(c => c.File("Logs/logs.txt"))
                // 异步写入日志到控制台
                .WriteTo.Async(c => c.Console())
                // 创建 Logger 实例
                .CreateLogger();

            // 创建并运行主机,异步执行
            await CreateHostBuilder(args).RunConsoleAsync();
        }

        // 配置和创建主机构建器
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                // 添加应用程序设置中的机密配置
                .AddAppSettingsSecretsJson()
                // 配置日志记录服务,清除默认的日志提供程序
                .ConfigureLogging((context, logging) => logging.ClearProviders())
                // 配置应用程序的服务
                .ConfigureServices((hostContext, services) =>
                {
                    // 添加 DbMigratorHostedService 作为托管服务
                    services.AddHostedService<DbMigratorHostedService>();
                });
    }
}

要点:

1.设置了不同命名空间的日志级别,并且将日志输出到控制台和txt(.\aspnet-core\src\Acme.BookStore.DbMigrator\bin\Debug\net8.0\Logs)

2.注册了一个托管服务,说直白点,启动了Programs.cs(即启动了应用程序),它会自动调用所有托管服务(DbMigratorHostedService)的 StartAsync 方法,当应用程序停止时(关闭控制台窗口时),宿主环境会自动调用所有托管服务的 StopAsync 方法。

【DbMigratorHostedService.cs】

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Acme.BookStore.Data;
using Serilog;
using Volo.Abp;

namespace Acme.BookStore.DbMigrator;

// DbMigratorHostedService 实现了 IHostedService 接口,用于在应用启动时执行数据库迁移
public class DbMigratorHostedService : IHostedService
{
    // IHostApplicationLifetime 用于在应用程序的生命周期中执行停止操作
    private readonly IHostApplicationLifetime _hostApplicationLifetime;
    // IConfiguration 用于访问应用程序的配置(例如:appsettings.json,拿它的连接字符串)
    private readonly IConfiguration _configuration;

    // 构造函数初始化 DbMigratorHostedService 的依赖项
    public DbMigratorHostedService(IHostApplicationLifetime hostApplicationLifetime, IConfiguration configuration)
    {
        _hostApplicationLifetime = hostApplicationLifetime;
        _configuration = configuration;
    }

    // StartAsync 方法在服务启动时被调用
    public async Task StartAsync(CancellationToken cancellationToken)//CancellationToken 可以用来中断长时间运行的任务或者进行一些清理操作
    {
        // 创建 Abp 应用程序实例
        using (var application = await AbpApplicationFactory.CreateAsync<BookStoreDbMigratorModule>(options =>
        {
            // 替换默认配置服务,使用自定义配置源(如 appsettings.json等)
            options.Services.ReplaceConfiguration(_configuration);
            // 使用 Autofac 作为依赖注入容器(支持自动解析和注入服务,使得服务之间能相互发现、注入)
            options.UseAutofac();
            // 添加 Serilog 作为日志记录工具
            options.Services.AddLogging(c => c.AddSerilog());
        }))
        {
            // 初始化应用程序
            await application.InitializeAsync();

            // 获取 BookStoreDbMigrationService 实例并执行数据库迁移
            await application
                .ServiceProvider
                .GetRequiredService<BookStoreDbMigrationService>()
                .MigrateAsync();

            // 关闭应用程序
            await application.ShutdownAsync();

            // 停止宿主应用程序
            _hostApplicationLifetime.StopApplication();
        }
    }

    // StopAsync 方法在服务停止时被调用
    public Task StopAsync(CancellationToken cancellationToken)
    {
        // 不需要执行任何操作,直接返回已完成的任务
        return Task.CompletedTask;
    }
}

要点:

1.入参(CancellationToken cancellationToken)的作用:它用于接收取消操作的信号,例如在服务启动或停止过程中,可以响应取消请求并进行相应的清理操作,请举例代码

2.实现 IHostedService 接口的意义:实现 IHostedService 接口的目的是为了使用StartAsync 和 StopAsync 方法用于处理程序启动和停止操作。

3.DbMigratorHostedService.cs 的StartAsync/StopAsync 方法:Program.cs 启动应用时会调用 StartAsync 方法,关闭应用时会调用 StopAsync 方法。

4.IHostApplicationLifetime 和 IConfiguration 的来源:这两个参数由依赖注入框架提供。在 ASP.NET Core 中,系统会自动将这些服务注入到你的构造函数中。

【BookStoreDbMigratorModule.cs】

using Acme.BookStore.EntityFrameworkCore; // 引入用于数据访问的 Entity Framework Core 模块
using Volo.Abp.Autofac; // 引入 ABP 框架的 Autofac 模块,以支持依赖注入
using Volo.Abp.BackgroundJobs; // 引入 ABP 框架的后台任务模块
using Volo.Abp.Modularity; // 引入 ABP 框架的模块化功能

namespace Acme.BookStore.DbMigrator // 定义命名空间,组织代码
{
    [DependsOn(
        typeof(AbpAutofacModule), // 该模块依赖于 Autofac 模块,用于支持依赖注入
        typeof(BookStoreEntityFrameworkCoreModule), // 该模块依赖于 BookStore 的 Entity Framework Core 模块,用于数据访问
        typeof(BookStoreApplicationContractsModule) // 该模块依赖于 BookStore 的应用程序合同模块
    )]
    public class BookStoreDbMigratorModule : AbpModule // 定义一个模块类,继承自 ABP 的 AbpModule 基类
    {
        public override void ConfigureServices(ServiceConfigurationContext context) // 重写 ConfigureServices 方法以配置服务
        {
            Configure<AbpBackgroundJobOptions>(options => options.IsJobExecutionEnabled = false); // 配置后台任务选项,禁用任务执行
        }
    }
}

1.继承AbpModule是为了重写ConfigureServices方法,ConfigureServices方法:

(1)有什么作用呢?

    向依赖注入容器中添加或修改服务的配置(有一些服务不想要,或者想添加一些服务)

(2)入参ServiceConfigurationContext context应该如何使用?

    var services = context.Services;// 获取 IServiceCollection 实例

    services.AddTransient<IMyService, MyService>();// 注册自定义服务

    services.AddScoped<MyMiddleware>();  // 添加自定义中间件

    context.Services.AddSingleton<IMyServiceFactory, MyServiceFactory>();    // 注册一个服务工厂

(3)为什么要写Configure<AbpBackgroundJobOptions>(options => options.IsJobExecutionEnabled = false)?

    迁移服务约定俗成的,在迁移期间防止后台任务的运行,以避免潜在的冲突或不必要的执行

2.为什么要依赖BookStoreApplicationContractsModule

    确保模块可以访问和使用 BookStore 应用程序的合同(接口和 DTOs),避免迁移出错

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 517ttc.cn 版权所有 赣ICP备2024042791号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务