Bài viết này hướng dẫn cách tách riêng logic Identity thành các dự án độc lập, cho phép dễ dàng chuyển đổi hoặc hỗ trợ nhiều loại cơ sở dữ liệu khác nhau (MySQL, SQL Server, PostgreSQL...) mà không làm ảnh hưởng đến code chính.
1. Tạo thư viện EF chung (ExtendEF)
Đầu tiên, tạo một thư viện lớp chứa các định nghĩa entity và DbContext dùng chung cho Identity.
Cấu hình dự án ExtendEF
File .csproj của ExtendEF cần tham chiếu các gói Identity và EF Core:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.0" />
</ItemGroup>
</Project>
Entity mở rộng cho Role
Thêm thuộc tính tùy chỉnh cho Role:
public class AppRole : IdentityRole
{
/// <summary>
/// Tên hiển thị của role
/// </summary>
public string DisplayName { get; set; }
}
Entity mở rộng cho User
Thêm các thuộc tính bổ sung cho User:
public class AppUser : IdentityUser
{
/// <summary>
/// Thành phố nơi người dùng sống
/// </summary>
public string City { get; set; }
/// <summary>
/// Biệt danh
/// </summary>
public string DisplayName { get; set; }
}
DbContext tùy chỉnh
Tạo DbContext kế thừa từ IdentityDbContext với các entity đã mở rộng:
public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
}
2. Tạo dự án triển khai cho MySQL (ExtendMySql)
Tiếp theo, tạo một thư viện riêng để cấu hình kết nối MySQL và xử lý Migration.
Cấu hình dự án ExtendMySql
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ExtendEF\ExtendEF.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Factory cho Migration
Lớp IDesignTimeDbContextFactory giúp tạo DbContext tại thời điểm thiết kế để thực hiện Migration:
public class AppDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
var connectionString = config.GetConnectionString("DefaultConnection");
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
var serverVersion = new MySqlServerVersion(new Version(8, 0, 27));
optionsBuilder.UseMySql(connectionString, serverVersion,
mysqlOptions => mysqlOptions.MigrationsAssembly(GetType().Assembly.FullName));
return new AppDbContext(optionsBuilder.Options);
}
}
File cấu hình appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=192.168.0.196;Database=IdentityMultiDb;uid=root;pwd=123456"
}
}
3. Tạo và áp dụng Migration
- Đặt dự án ExtendMySql làm startup project.
- Trong Package Manager Console, chọn default project là ExtendMySql.
- Chạy lệnh:
add-migration InitExtendedUsersAndRoles - Sau đó chạy:
update-database
Sau khi hoàn tất, kiểm tra database MySQL đã được tạo với các bảng Identity mở rộng.