Các Thư Viện Cơ Bản Cần Thiết Khi Triển Khai Domain-Driven Design Trong .NET

Cấu Hình Serializer JSON

Cấu hình để chuyển đổi tên thuộc tính thành dạng camelCase cho phản hồi API:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<GlobalExceptionFilter>();
})
.AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});

Cài Đặt Health Checks

Cấu hình kiểm tra trạng thái ứng dụng và tích hợp giao diện UI:

builder.Services.AddHealthChecks()
    .AddCheck("app-status", _ => HealthCheckResult.Healthy(), tags: new[] { "application" });
app.UseHealthChecks("/api/health", new HealthCheckOptions
{
    Predicate = _ => true,
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

app.UseHealthChecks("/api/self-check", new HealthCheckOptions
{
    Predicate = result => result.Tags.Contains("application")
});

app.UseHealthChecksUI(setup =>
{
    setup.UIPath = "/health-ui";
});

Cấu Hình Health Checks Trong appsettings.json

{
  "HealthChecksUI": {
    "HealthChecks": [
      {
        "Name": "Application Status",
        "Uri": "/api/health"
      }
    ],
    "EvaluationTimeinSeconds": 15,
    "MinimumSecondsBetweenFailureNotifications": 60
  }
}

Cấu Hình Kết Nối MySQL Với Retry Policy

builder.Services.AddDbContext<IntegrationEventLogContext>(options =>
{
    string mysqlConn = builder.Configuration.GetConnectionString("mysql") ?? throw new InvalidOperationException("Connection string not found");
    options.UseMySql(mysqlConn, new MySqlServerVersion(new Version(8, 0, 27)), dbOptions =>
    {
        dbOptions.MigrationsAssembly(typeof(IntegrationEventLogContext).Assembly.GetName().Name);
        dbOptions.EnableRetryOnFailure(maxRetryCount: 10, TimeSpan.FromSeconds(10), null);
    });
});

Cấu Hình Chuỗi Kết Nối Trong appsettings.json

{
  "ConnectionStrings": {
    "mysql": "server=192.168.1.100;port=3306;database=DomainApp;password=securepass;userid=admin;"
  }
}

Xử Lý Giao Dịch Với Retry Strategy

public async Task ExecuteWithRetry(Func<Task> action)
{
    var retryStrategy = dbContext.Database.CreateExecutionStrategy();
    await retryStrategy.ExecuteAsync(async () =>
    {
        await using var transaction = await dbContext.Database.BeginTransactionAsync();
        await action();
        await transaction.CommitAsync();
    });
}

Cấu Hình MediatR

builder.Services.AddMediatR(config =>
{
    config.RegisterServicesFromAssembly(typeof(Startup).Assembly);
});

Cấu Hình AutoMapper

builder.Services.AddAutoMapper(options =>
{
    options.AddMaps(typeof(Startup).Assembly);
});

Ví Dụ Định Nghĩa Mapper

public class UserMappingProfile : Profile
{
    public UserMappingProfile()
    {
        CreateMap<InvoiceInput, Invoice>().ReverseMap();
        CreateMap<InvoiceDto, Invoice>().ReverseMap();
        CreateMap<UserDto, User>()
            .ForMember(dest => dest.Invoices, opt => opt.MapFrom(src => src.InvoiceList))
            .ReverseMap();
        CreateMap<UserInput, User>()
            .ForMember(dest => dest.Invoices, opt => opt.MapFrom(src => src.InvoiceInputs))
            .ReverseMap();
    }
}

Thẻ: Domain-Driven Design MediatR Dapper grpc automapper

Đăng vào ngày 9 tháng 7 lúc 09:29