繁体   English   中英

Ef core 6 尝试使用时抛出错误 500.ThenInclude 方法

[英]Ef core 6 throws error 500 when trying to use .ThenInclude method

我有两个表 Employee 和 Skill,它们使用与 EmployeeSkill 关联 class 的多对多关系连接。 但是,下面的查询可以正常工作:1] 当我调用 employees 方法时,我得到了正确数量的 Counted Skill 引用对象,但它们都被初始化为零,2] 当我尝试添加 ThenInclude 查询时,它会抛出 500 错误。

非常感谢您的宝贵时间

编辑:一种解决方案是向 Startup.cs 添加以下代码行:

services.AddControllers().AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);

服务器异常:

执行请求时发生未处理的异常。 System.Text.Json.JsonException:检测到可能的 object 循环。 这可能是由于循环或 object 深度大于最大允许深度 32

客户端异常:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Response status code does not indicate success: 500 (Internal Server Error).
System.Net.Http.HttpRequestException: Response status code does not indicate success: 500 (Internal Server Error).
   at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
   at System.Net.Http.HttpClient.GetStreamAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   at SkillMatrix.Client.Services.EmployeeDataService.GetEmployeesAsync() in C:\Users\Onelity-mefraimidis\Downloads\Onelity related\.NET projects\SkillMatrix\SkillMatrix.Client\Services\EmployeeDataService.cs:line 30
   at SkillMatrix.Client.Features.EmployeeView.EmployeeOverviewPage.OnInitializedAsync() in C:\Users\Onelity-mefraimidis\Downloads\Onelity related\.NET projects\SkillMatrix\SkillMatrix.Client\Features\EmployeeView\EmployeeOverviewPage.cs:line 54
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

上下文(在 sql 数据库中正确添加):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // Configure a Many-to-Many Relationship using Fluent API   
    modelBuilder.Entity<Employee>()
                .HasMany(e => e.Skills)
                .WithMany(s => s.Employees)
                .UsingEntity<EmployeeSkill>(
        j => j.HasOne(m => m.Skill).WithMany(g => g.EmployeeSkills),
        j => j.HasOne(m => m.Employee).WithMany(g => g.EmployeeSkills),
        je =>
        {
            je.HasKey("EmployeesId", "SkillsId");
            je.HasData(
                new EmployeeSkill { EmployeesId = 1, SkillsId = 1 },
                new EmployeeSkill { EmployeesId = 1, SkillsId = 3 },
                new EmployeeSkill { EmployeesId = 1, SkillsId = 4 },
                new EmployeeSkill { EmployeesId = 1, SkillsId = 5 },
                new EmployeeSkill { EmployeesId = 1, SkillsId = 8 },

                new EmployeeSkill { EmployeesId = 2, SkillsId = 1 },
                new EmployeeSkill { EmployeesId = 2, SkillsId = 2 },
                new EmployeeSkill { EmployeesId = 2, SkillsId = 3 },
                new EmployeeSkill { EmployeesId = 2, SkillsId = 11 },
                new EmployeeSkill { EmployeesId = 2, SkillsId = 15 },

                new EmployeeSkill { EmployeesId = 3, SkillsId = 10 },
                new EmployeeSkill { EmployeesId = 3, SkillsId = 22 },
                new EmployeeSkill { EmployeesId = 3, SkillsId = 23 },
                new EmployeeSkill { EmployeesId = 3, SkillsId = 40 },
                new EmployeeSkill { EmployeesId = 3, SkillsId = 47 }
                );
        }
        );

课程:

public class EmployeeSkill
{
    public int SkillsId;
    public int EmployeesId;

    public Employee Employee;
    public Skill Skill;
}

public class Employee
{
    public int Id { get; set; }

    [Required]
    [StringLength(50, ErrorMessage = "First name is too long.")]
    public string FirstName { get; set; }

    [Required]
    [StringLength(50, ErrorMessage = "Last name is too long.")]
    public string LastName { get; set; }

    public DateTime DateOfBirth { get; set; }

    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [Phone]
    public string PhoneNumber { get; set; }

    public bool Smoker { get; set; }

    public MaritalStatus MaritalStatus { get; set; }

    public Gender Gender { get; set; }

    [StringLength(1000, ErrorMessage = "Comment length cannot exceed 1000 characters.")]
    public string Comment { get; set; }

    public DateTime? JoinedDate { get; set; }

    public DateTime? LastUpdateDate { get; set; }

    public DateTime? ExitDate { get; set; }

    public int JobCategoryId { get; set; }

    public JobCategory JobCategory { get; set; }

    #region Navigation Properties
    public virtual EmployeeAddress Address { get; set; }

    public virtual ICollection<Skill> Skills { get; set; }
    public virtual ICollection<EmployeeSkill> EmployeeSkills { get; set; }

    #endregion
}

public class Skill
{
    public int Id { get; set; }

    [Required]
    [StringLength(50, ErrorMessage = "Name is too long.")]
    public string Name { get; set; }

    public string Description { get; set; }

    public Level Level { get; set; }

    public int SkillCategoryId { get; set; }

    #region Navigation Properties
    public virtual SkillCategory SkillCategory { get; set; }

    public virtual ICollection<Employee> Employees { get; set; }
    public virtual ICollection<EmployeeSkill> EmployeeSkills { get; set; }

    #endregion
}

服务方式:

public async Task<IEnumerable<EmployeeSkillResponse>> GetEmployeeSkillsAsync()
{
    return await JsonSerializer.DeserializeAsync<IEnumerable<EmployeeSkillResponse>>(await _httpClient.GetStreamAsync("api/employeeskills"),
                                    new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
}

存储库:

public IEnumerable<Employee> GetEmployees()
{
    var query1 = _skillMatrixContext.Employees.Include(employee => employee.EmployeeSkills).ToList();

    // initially was query
    //var query = _skillMatrixContext.Employees;

    // this throws 500 error
    //var query2 = _skillMatrixContext.Employees.Include(employee => employee.EmployeeSkills).ThenInclude(skill=>skill.Skill).ToList();
    
    return query1;
}

Controller 方法:

[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<EmployeeResponse>))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[Produces(MediaTypeNames.Application.Json)]
public ActionResult<IEnumerable<EmployeeResponse>> GetEmployees()
{
    var employeesFromRepo = _employeeRepository.GetEmployees();

    return Ok(_mapper.Map<IEnumerable<EmployeeResponse>>(employeesFromRepo));
}

一种解决方案是向 Startup.cs 添加以下代码行:

services.AddControllers().AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);

还必须注意 AsNoTracking() 可以在查询结束时使用。 引用 Svyatoslav Danyliv: EF Core fixup navigation properties via ChangeTracker,它可能会导致加载对象中的循环引用——这就是你有异常的原因。 AsNoTracking() 禁用此修复和更改跟踪,这可能会加速加载记录。 通常在写API的时候,它使用DTO类通过网络返回信息,这样的问题几乎不会出现

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM