我正在使用.NET 8,当在主构造函数中调用时,我的
DbContext
为空,但在普通构造函数中调用时。
这是我的
DbContext
:
public class DataContext(DbContextOptions<DataContext> options) : DbContext(options)
{
public DbSet<Student> Students { get; set; }
public DbSet<Subject> Subjects { get; set; }
public DbSet<Teacher> Teachers { get; set; }
public DbTSet<Lesson> Lessons { get; set; }
public DbSet<Attendance> Attendances { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.AddInboxStateEntity();
builder.AddOutboxMessageEntity();
builder.AddOutboxStateEntity();
builder.Ignore<BaseEntity>();
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
foreach (var entity in ChangeTracker
.Entries()
.Where(x => x is { Entity: BaseEntity, State: EntityState.Modified })
.Select(x => x.Entity)
.Cast<BaseEntity>())
entity.UpdatedAt = DateTime.UtcNow;
return base.SaveChangesAsync(cancellationToken);
}
}
我的控制器:
[ApiController]
[Route("api/[controller]")]
public class SubjectsController(DataContext context, IMapper mapper) : ControllerBase
{
[HttpGet("{room}")]
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
[AuthorizeForScopes(ScopeKeySection = "AzureAd:Scopes")]
public async Task<ActionResult<SubjectDto>> GetByRoom(string room)
{
var userId = Guid.Parse(User.GetObjectId());
var students = await context.Students.OrderBy(x => x.StudentCode).ToListAsync();
var student = await context.Students.FirstOrDefaultAsync(x => x.Id == userId);
if (student == null)
return NotFound("Student not found");
var now = DateOnly.FromDateTime(DateTime.UtcNow);
var subject = await context.Subjects
.Include(x => x.Students)
.AsSplitQuery()
.Where(x => x.Students.Contains(student))
.ProjectTo<SubjectDto>(mapper.ConfigurationProvider)
.FirstOrDefaultAsync(x =>
x.Room.Equals(room, StringComparison.CurrentCultureIgnoreCase)
&& x.DateStart <= now && now <= x.DateEnd
&& !x.IsEnded);
if (subject == null)
return NotFound("Subject not found");
return subject;
}
}
当我执行时:
具有主构造函数
使用普通构造函数
当我调用主构造函数时,我希望
DbContext
不为空
更新:
我的程序.cs:
using ApplicationBase.Extensions;
using MassTransit;
using Microsoft.EntityFrameworkCore;
using Polly;
using StudentService.Consumers;
using StudentService.Data;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services.AddEndpointsApiExplorer();
builder.Services.AddControllers();
builder.Services.AddIdentityService(builder.Configuration);
builder.Services.AddDbContext<DataContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))
);
builder.Services.AddMassTransit(opts =>
{
opts.AddEntityFrameworkOutbox<DataContext>(opt =>
{
opt.QueryDelay = TimeSpan.FromSeconds(10);
opt.UseSqlServer();
opt.UseBusOutbox();
});
opts.AddConsumersFromNamespaceContaining<StudentAuthConsumer>();
opts.SetEndpointNameFormatter(new KebabCaseEndpointNameFormatter("student-svc", false));
opts.UsingRabbitMq((context, cfg) =>
{
cfg.UseMessageRetry(r =>
{
r.Handle<RabbitMqConnectionException>();
r.Interval(5, TimeSpan.FromSeconds(10));
});
cfg.Host(builder.Configuration["RabbitMQ:Host"], "/", host =>
{
host.Username(builder.Configuration.GetValue("RabbitMQ:Username", "guest"));
host.Password(builder.Configuration.GetValue("RabbitMQ:Password", "guest"));
});
cfg.ConfigureEndpoints(context);
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseApplicationIdentity();
app.MapControllers();
var retryPolicy = Policy
.Handle<Exception>()
.WaitAndRetry(5, _ => TimeSpan.FromSeconds(10));
retryPolicy.ExecuteAndCapture(() => app.InitDb());
app.Run();
第二张图中具有普通构造函数的控制器:
using AutoMapper;
using AutoMapper.QueryableExtensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Web;
using StudentService.Data;
using StudentService.DTOs;
using StudentService.Models;
namespace StudentService.Controllers;
[ApiController]
[Route("api/[controller]")]
public class SubjectsController : ControllerBase
{
private readonly DataContext _context;
private readonly IMapper _mapper;
public SubjectsController(DataContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
[HttpGet("{room}")]
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
[AuthorizeForScopes(ScopeKeySection = "AzureAd:Scopes")]
public async Task<ActionResult<SubjectDto>> GetByRoom(string room)
{
var userId = Guid.Parse(User.GetObjectId());
if (!await _context.Students.AnyAsync(x => x.Id == userId))
return NotFound("Student not found");
var dateTimeNow = DateTime.UtcNow;
var dateNow = DateOnly.FromDateTime(dateTimeNow);
var subject = await _context.Subjects
.AsSplitQuery()
.Include(x => x.Students)
.Where(x => x.Students.Any(s => s.Id == userId))
.Include(x => x.Lessons)
.Where(x => x.Lessons.Any(l => l.StartTime <= dateTimeNow && dateTimeNow <= l.EndTime))
.ProjectTo<SubjectDto>(_mapper.ConfigurationProvider)
.FirstOrDefaultAsync(x =>
x.Room.ToLower().Contains(room.ToLower())
&& x.DateStart <= dateNow && dateNow <= x.DateEnd
&& !x.IsEnded
);
if (subject == null) return NotFound("Subject not found");
return subject;
}
[HttpPost]
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
[AuthorizeForScopes(ScopeKeySection = "AzureAd:Scopes")]
public async Task<ActionResult<SubjectDto>> Create(SubjectCreateDto subjectCreateDto)
{
var userId = Guid.Parse(User.GetObjectId());
if (!await _context.Teachers.AnyAsync(x => x.Id == userId))
return NotFound("Teacher not found");
var subject = _mapper.Map<Subject>(subjectCreateDto);
subject.Students.Add(new Student { Id = userId });
await _context.Subjects.AddAsync(subject);
var result = await _context.SaveChangesAsync() > 0;
if (!result) return BadRequest();
return _mapper.Map<SubjectDto>(subject);
}
}
我的包裹:
这是由控制器中的异步方法引起的。例如,修改如下代码:
public class TestsController(DataContext _context) : Controller
{
// public async Task<IActionResult> Index()
public IActionResult Index()
{
//return View(await _context.Test.ToListAsync());
return View(_context.Test.ToListAsync());
}
}