在 .NET 8 上的主构造函数 EF Core 中调用时,DbContext 为 Null

问题描述 投票:0回答:1

我正在使用.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;
    }
}

当我执行时:

  • 具有主构造函数

    With primary constructor

  • 使用普通构造函数

    With normal constructor

当我调用主构造函数时,我希望

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);
    }
}

我的包裹:

  • 主要服务: Main service
  • 基础服务: Base service
c# .net entity-framework asp.net-core .net-8.0
1个回答
0
投票

这是由控制器中的异步方法引起的。例如,修改如下代码:

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());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.