0%

01.DotNet Core Blog:基于EFCore数据库设计与开发

使用Asp.Net Core设计开发个人博客:第一阶段数据库设计

1.数据库设计

文章表(PaperTable)

变量名称 描述 类型
ID 唯一ID int
Title 文章标题 nvarchar(30)
Content 内容 text
Time 创建时间 DateTime
PaperTypeID 文章类型ID(考虑使用外键) int
Browers 浏览量 int
Supports 点赞 int
AuthorID 作者ID int

文章类型表(PaperID)

变量名称 描述 类型
ID 唯一ID int
Name 类型名 nvarchar(30)

作者表(AuthorID)

变量名称 描述 类型
ID 唯一ID int
Name 姓名 nvarchar(12)
UserName 账号 nvarchar(16)
UserPwd 密码(MD5加密) nvarchar(64)

2.数据库开发

2.1 NuGet 安装EFCore的相关库

EFCore MySql需要的库

数据库系统 配置示例 NuGet程序包
SQLServer
AzureSQL
.UseSqlServer(connectionString) Microsoft.EntityFrameworkCore.SqlServer
Azure Cosmos DB .UseCosmos(connectionString, databaseName) Microsoft.EntityFrameworkCore.Cosmos
SQLite .UseSqlite(connectionString) Microsoft.EntityFrameworkCore.Sqlite
EFCore内存中数据库 .UseInMemoryDatabase(databaseName) Microsoft.EntityFrameworkCore.InMemory
PostgreSQL* .UseNpgsql(connectionString) Npgsql.EntityFrameworkCore.PostgreSQL
MySQL/MariaDB* .UseMySql((connectionString) Pomelo.EntityFrameworkCore.MySql
Oracle* .UseOracle(connectionString) Oracle.EntityFrameworkCore

2.2 Model库的类设计,与数据库上下文绑定在一起

2.2.1 实体属性

使用实体属性将模型类映射到列表(详见微软EFCore官方文档)

  • [Key]:主键
  • [NotMapped]:排除特定属性
  • [Column("xxx")]:指定列名
  • [Column(TypeName="nvarchar(200)")],[Column(TypeName = "decimal(5, 2)")]:指定属性类型
  • [MaxLength(500)]:指定最大长度
  • [required]:属性值不可以为NULL
  • [optional]:属性值可以为NULL
  • [DatabaseGenerated(DatabaseGeneratedOption.Identity)]非主键,自动生成键值,如日期
  • [DatabaseGenerated(DatabaseGeneratedOption.None)]无值生成

通用属性ID >>> 继承

1
2
3
4
5
public class BaseId
{
[Key]
public int Id { get; set; }
}

AuthorTable设计

1
2
3
4
5
6
7
8
9
10
11
12
[Table("AuthorTable")]
public class AuthorInfo:BaseId
{
[Column(TypeName = "nvarchar(12)")]
public string Name { get; set; }

[Column(TypeName = "nvarchar(16)")]
public string UserName { get; set; }

[Column(TypeName = "nvarchar(64)")]
public string UserPwd { get; set; }
}

PaperTypeTable设计

1
2
3
4
5
6
[Table("PaperTypeTable")]
public class PaperTypeInfo:BaseId
{
[Column(TypeName = "nvarchar(12)")]
public string Name { get; set; }
}

PaperTable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Table("PaperTable")]
public class PaperInfo:BaseId
{
[Column(TypeName = "nvarchar(30)")]
public string Title { get; set; }
[Column(TypeName = "text")]
public string Content { get; set; }
public DateTime Time { get; set; }
public int Browers { get; set; }
public int Supports { get; set; }
public int AuthorId { get; set; }
public int PaperTypeId { get; set; }

// 该数据类型不映射至数据库
[NotMapped]
public PaperTypeInfo PaperType { get; set; }
[NotMapped]
public AuthorInfo Author { get; set; }
}

DbContext 生存期、配置和初始化

步骤:

  • 创建 DbContext 上下文实例
  • 根据上下文实例执行CRUD操作
  • 调用 SaveChanges 或 SaveChangesAsync将上述操作写入数据库中
  • 释放DbContext

方法1: ASP.NET Core 依赖关系注入中的 DbContext

  1. 创建上下文类
    ApplicationDbContext类必须公开具有DbContextOptions参数的公共构造函数。这是将 AddDbContext的上下文配置传递到DbContext的方式
    1
    2
    3
    4
    5
    6
    7
    public class ApplicationDbContext : DbContext
    {
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : base(options)
    {
    }
    }
  2. 使用Startup.cs的ConfigureServices方法中的AddDbContext 将 EF Core 添加到此配置。
1
2
3
4
5
6
7
8
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<ApplicationDbContext>(
options => options.UseMySql("server=127.0.0.1;user id=root;persistsecurityinfo=True")
) ;
}

方法2: 使用”new”的简单的 DbContext 初始化

1
2
3
4
5
6
7
public class ApplicationDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySql(@"server=127.0.0.1;user id=root;persistsecurityinfo=True");
}
}

或者通过构造函数传递 连接字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ApplicationDbContext : DbContext
{
private readonly string _connectionString;

public ApplicationDbContext(string connectionString)
{
_connectionString = connectionString;
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySql(_connectionString);
}
}

在或者

1
2
3
4
5
var contextOptions = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseMySql(@"Server=(localdb)\mssqllocaldb;Database=Test")
.Options;

using var context = new ApplicationDbContext(contextOptions);

DbContext 使用

1
2
3
4
5
6
7
8
9
public class MyController
{
private readonly ApplicationDbContext _context;

public MyController(ApplicationDbContext context)
{
_context = context;
}
}

2.2.2 为每个Table建立通用CRUD接口库

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
31
32
33
34
35
36
37
38
39
40
public interface IBaseRepository<TEntity> where TEntity:class,new()
{
#region [CRUD]
Task<bool> CreateAsync(TEntity entity);
Task<bool> DeleteAsync(int id);
Task<bool> UpdateAsync(TEntity entity);
Task<TEntity> QueryAsync(int id);
#endregion
/// <summary>
/// 查询所有数据
/// </summary>
/// <returns></returns>
Task<List<TEntity>> QueryAllAsync();

/// <summary>
/// 自定义查询条件
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
Task<List<TEntity>> QueryAsync(Expression<Func<TEntity,bool>> func);

/// <summary>
/// 分页查询
/// </summary>
/// <param name="page">设置跳转的页码</param>
/// <param name="size">每页的数量</param>
/// <param name="total">总数目</param>
/// <returns></returns>
Task<List<TEntity>> QueryAsync(int page,int size,ref int total);

/// <summary>
/// 自定义查询 + 分页
/// </summary>
/// <param name="func"></param>
/// <param name="page"></param>
/// <param name="size"></param>
/// <param name="total"></param>
/// <returns></returns>
Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> func,int page, int size, ref int total);
}

2.2.3 实现通用CRUD库

1