文章管理系统——后端(一)

  • 主要技术栈:.net Core
  • 这一章主要讲 .net Core 的结构。

系统目录与功能分区

002.png

上面是后台管理系统的结构,我给它分了三层,其中 API 负责与前端交互,Domain 是领域层,负责处理业务逻辑,Data 是数据层,数据相关的都在里面。

在这个基础上,我又细分了多层:

  • API:主项目层
  • Bussiness:业务逻辑层
  • IService:数据接口层
  • Service:数据层
  • Entity:实体层
  • Model:模型层

API:主项目层

001.png

这一层主要的就是 Controllers(控制器),它细分为 AdminClient,这是为了以后扩展更方便。

Bussiness:业务逻辑层

003.png

同样的,这里也分为了 AdminClient,这也是为了以后扩展更方便。

IService:数据接口层

该层为数据接口层,里面只罗列了相应的接口函数,但是具体的函数功能实现则交给继承该数据接口的数据层来实现。

这样做的好处是可以将数据库操作与代码逻辑操作分离的更加清晰。

Service:数据层

该层负责直接或者间接对数据库进行操作,如果你是用原生的或者类似Dapper的数据库中间件,那么在这一层就会看到相应的sql语句。我把 IService 给了 Domain,而 Service 给了 Data,因为前者处理业务逻辑,后者直接处理数据,当然,这是我第一次这样写,有不对的欢迎指正。

Entity:实体层

该层为实体类层,存储了数据库对应的所有实体,实体一般和数据库表是一一对应的。我这里准备 EF 自动生成

Model:模型层

该层我准备用作 Entity 的补充,刚从 MVC 过来,有点小习惯……

Service.Base:辅助层

该层存放了一些系统帮助类,或是实体辅助类。

这个层还没确定建立……等以后再改吧。

数据库连接

建立实体类

Model 下面建立一个类,里面的内容与数据库表里的内容相对应。

例如我建立了一个 Role 表,则 Model 下面的类就是:RoleModel

1
2
3
4
5
6
7
8
9
10
11
12
using System;

namespace AMS.Model
{
public class RoleModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int IsDelete { get; set; }
}
}

上下文类

再在 Model 类库里面创建一个上下文类 CoreDbContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;

namespace AMS.Model
{
public class CoreDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(@"Data Source=.;Initial Catalog=XX_AMS;Integrated Security=True");
}
}

public virtual DbSet<RoleModel> T_Role { get; set; }
}
}

CoreDbContext 类继承 DbContextDbContext是EF框架中非常重要的一个环节,是建立实体类与数据库连接的桥梁。

这里我们写了连接数据库的字符串,同时把 RoleModel 给了它,这样我们就连接到数据库了。

控制器

Controllers/Admin 下面新建一个 RoleController.cs 控制器,里面写入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;

namespace AMS.Model
{
public class CoreDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(@"Data Source=.;Initial Catalog=XX_AMS;Integrated Security=True");
}
}

public virtual DbSet<RoleModel> T_Role { get; set; }
}
}

这里使用了 Model 里面的类容,所有我们要把 Model 的引用 API 里面,然后直接运行,定位到 admin/role/RoleGetList 就可以在浏览器中查看结果了。

数据库连接优化

将连接字符串写入 API 下面的 appsettings.json,其代码修改如下:

1
2
3
4
5
6
7
8
9
10
11
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"connectionStrings": {
"conn": "Data Source=.;Initial Catalog=XX_AMS;Integrated Security=True"
}
}

然后去修改 Startup.cs,将里面 ConfigureServices 的添加:

1
2
services.AddDbContext<CoreDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("conn")));

修改上下文类为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;

namespace AMS.Model
{
public class CoreDbContext : DbContext
{
public CoreDbContext(DbContextOptions<CoreDbContext> options)
: base(options)
{ }

public virtual DbSet<RoleModel> T_Role { get; set; }
}
}

这时其实是已经把coreDbContext注入到容器中进行操作,而容器中对Context的注入方式为瞬时注入,因此后面要用到依赖注入的时候,很多时候,在数据层使用context的时候需要把对应的注入都设计为瞬时注入的形式,此处就不进行过多的提及。

我们在进行测试一下,这下我们就不用自己进行context的new操作,由于我们一开始进行设置的时候就已经进行了依赖注入的形式,不过,.netCore中只有构造注入,没有属性注入,因此我们就用构造注入的方式进行,修改 RoleController.cs 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AMS.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace AMS.API.Controllers.Admin
{
[Route("admin/[controller]/[action]")]
[ApiController]
public class RoleController : ControllerBase
{
private readonly CoreDbContext _coreDbContext;

public RoleController(CoreDbContext coreDbContext)
{
_coreDbContext = coreDbContext;
}


[HttpGet]
public List<RoleModel> RoleGetList()
{
return _coreDbContext.Set<RoleModel>().ToList();
}
}
}

我们使用构造函数进行构造注入。然后直接使用 ToList() 获取所有的数据。

直到这里,我们已经能够在 /admin/role/RoleGetList 里面看到我们获取到的所有数据了。

CORS 配置

最后的最后,我们进行一下 CORS 配置,在 APIStartup.csConfigureServices 写入:

1
services.AddCors();

然后在 Configure 里面写入:

1
2
3
4
5
6
app.UseCors(builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseMvc();

当然,这里配置的是允许全部,你也可以针对性的配置,详情可看 https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-2.2,我这里就这样配置了,以后再改。

swagger

使用 seagger

使用 swagger 来查看 api

APIStartup.csConfigureServices 中写入:

1
2
3
4
5
6
7
8
9
10
11
12
#region Swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Version = "v0.1.0",
Title = "Blog.Core API",
Description = "框架说明文档",
TermsOfService = "None",
});
});
#endregion

APIStartup.csConfigure 中写入:

1
2
3
4
5
6
7
#region Swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1");
});
#endregion

修改 swagger 为启动页,在 APIPropertieslaunchSettings.json 里面修改 profilesIIS Express 中的 launchUrlswagger,此时启动页面就可以看到效果了。

显示注释

api 的属性 => 生成 => 输出,勾选 XML 文档文件,打开输出,根据提示给各个方法添加注释。

然后去修改 Startup.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#region Swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Version = "v0.1.0",
Title = "AMS.Core.API API",
Description = "API说明文档",
TermsOfService = "None",
Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "AMS.Core", Email = "2533566560@qq.com", Url = "https://lemonsea.github.io/" }
});

// 显示注释
// Core 2.0
var basePath = PlatformServices.Default.Application.ApplicationBasePath;
// Core 2.1
//var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "AMS.Core.API.xml");//这个就是刚刚配置的xml文件名
c.IncludeXmlComments(xmlPath, true);//默认的第二个参数是false,这个是controller的注释,记得修改
});
#endregion

在启动服务就可以看见每个 api 后面都有我们写的注释了。

自动生成实体

1
Scaffold-DbContext -Connection "Data Source=.;Initial Catalog=XX_AMS;Integrated Security=True" -Provider "Microsoft.EntityFrameworkCore.SqlServer" -OutputDir Models

更新表:

1
Scaffold-DbContext -Connection "Data Source=.;Initial Catalog=XX_AMS;Integrated Security=True" -Provider "Microsoft.EntityFrameworkCore.SqlServer" -OutputDir Models -Force
0%