首先,我展示一下我的数据库相关类:
DbContext.cs
public class BookingDbContext : DbContext
{
public BookingDbContext(DbContextOptions<BookingDbContext> options) : base(options)
{ }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
optionsBuilder.UseNpgsql("Server=localhost;Port=5432;User Id=postgres;Password=password;Database=db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Place>()
.HasOne(p => p.Address)
.WithOne(ad => ad.Place)
.HasForeignKey<Address>(ad => ad.PlaceId)
.OnDelete(DeleteBehavior.Cascade);
}
public DbSet<Place> Places { get; set; }
public DbSet<Address> Addresses { get; set; }
}
程序.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<BookingDbContext>();
builder.Services.AddTransient<IPlaceService, PlaceService>();
builder.Services.AddTransient<IPlaceRepository, PlaceRepository>();
builder.Services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
我像往常一样创建了 CRUD 方法,因此添加、删除、更新和获取。前 3 种方法工作没有问题,只有 GET 失败。 我收到一条错误消息:
System.InvalidOperationException: No database provider has been configured for this DbContext.
A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider.
If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
你知道这可能是什么原因吗?正如我之前所说 - 当我向数据库添加或删除某些内容时,一切正常。仅对于 get 方法,我遇到了这样的错误。
编辑:
public async Task<IEnumerable<Place>> GetPlaces(bool includeAddress)
{
if (includeAddress)
{
return await _dbContext.Places.Include(a => a.Address).ToListAsync();
}
else
{
return await _dbContext.Places.ToListAsync();
}
}
public async Task<Place> GetById(int id)
{
Place? place = await _dbContext.Places
.Where(p => p.Id == id)
.Include(p => p.Address)
.FirstOrDefaultAsync();
return place ?? throw new KeyNotFoundException($"Place with id: {id} not found.");
}
我的想法是,当您的 DbContext 服务注册为 Scoped 时,它的实例将像工作单元一样执行,并且生命周期很短。也许您的 GET 过程执行不止一项工作,并且在您的工作完成之前实例就已被释放。您可以尝试使用 AddDbContextFactory 方法:
builder.Services.AddDbContextFactory<BookingDbContext>();
并在 using 块中包含每个作业,创建 DbContext:
using (var db = _contextFactory.CreateDbContext())
{
...get operation code
}
这样db在所有get操作之后肯定会被处理掉。