我有太多实体,注册每个实体都让我头疼,更不用说实例化 dbcontext 的负载了。 所以我尝试动态注册数据库集。
为了将 DbSet 动态注册到 DbContext 中,我使用了此链接中的文章: 文字 我添加了扩展名作为文件:
public static class ModelBuilderExtensions
{
public static void RegisterAllEntities<BaseModel>(this ModelBuilder modelBuilder, params Assembly[] assemblies)
{
IEnumerable<Type> types = assemblies.SelectMany(a => a.GetExportedTypes()).Where(c => c.IsClass && !c.IsAbstract && c.IsPublic &&
typeof(BaseModel).IsAssignableFrom(c));
foreach (Type type in types)
modelBuilder.Entity(type);
}
}
然后我创建了一个名为 BaseEntity 的抽象类,我的所有实体都实现了它。
在 ApplicationDbContext 内部我重写了 OnModelCreating 方法:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var entitiesAssemblyInt = typeof(BaseEntity<int>).Assembly;
var entitiesAssemblyGuid = typeof(BaseEntity<Guid>).Assembly;
modelBuilder.RegisterAllEntities<BaseEntity<int>>(entitiesAssemblyInt);
modelBuilder.RegisterAllEntities<BaseEntity<Guid>>(entitiesAssemblyGuid);
}
它在迁移中完美运行,但是当我想在 commandHandler 中使用 dbcontext 将一行添加到名为 client 的表中时,我不知道如何从上下文调用 client。
context.Client.Add(客户端);
不起作用,因为我没有将 dbset 直接注册到 dbcontext 中,并且上下文中没有客户端。
在我看来,这通常是一个坏主意*,出于可维护性、调试、可读性的原因......这样的例子不胜枚举。
但是,如果必须,您可以使用
_context.Set<Donation>()
来获取给定实体的 DbSet。
示例
以下代码具有正确注册的 DbSet 和上下文。
这是 推荐方式
public async Task<Donation?> GetDonationAsync(Guid donationID)
{
return await _context.Donations
.Where(x => x.ID == donationID)
.SingleOrDefaultAsync();
}
public async Task AddDonationAsync(Donation donation)
{
await _context.Donations.AddAsync(donation);
}
与使用
context.Set<>()
相同:
public async Task<Donation?> GetDonationAsync(Guid donationID)
{
return await _context.Set<Donation>()
.Where(x => x.ID == donationID)
.SingleOrDefaultAsync();
}
public async Task AddDonationAsync(Donation donation)
{
await _context.Set<Donation>().AddAsync(donation);
}
上面的代码包含在我的存储库服务中。我建议这样做并调用您的存储库,而不是直接调用您的数据库上下文。
示例
存储库示例
public class DonationRepository : IDonationRepository
{
private readonly MyDatabaseContext _context;
public DonationRepository(MyDatabaseContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<Donation?> GetDonationAsync(Guid donationID)
{
return await _context.Donations
.Where(x => x.ID == donationID)
.SingleOrDefaultAsync();
}
public async Task AddDonationAsync(Donation donation)
{
await _context.Donations.AddAsync(donation);
}
}
控制器示例
[ApiController]
[Route("[controller]")]
public class DonationController : Controller
{
private readonly IDonationRepository _donationRepository;
private readonly ILogger<DonationController> _logger;
public DonationController(ILogger<DonationController> logger,
IDonationRepository donationRepository)
{
_logger = logger;
_donationRepository = donationRepository;
}
[HttpGet]
[Route("GetDonationValue")]
public async Task<IActionResult> GetDonationValueAsync(Guid donationID)
{
var donation = await _donationRepository.GetDonationAsync(donationID);
// Doesn't exist!
if (donation == null) {
_logger.LogError($"Couldn't find Donation with ID: '{donationID}'.");
return NotFound();
}
_logger.LogInformation($"Found Donation with value of: '{donation.Amount}'.");
return Ok(donation.Amount);
}
}