c# - EF Core 多对多使用 Automapper 在 API 资源上返回循环
问题描述
我将 .net Core 与 EF2 一起使用,我想设置这种多对多关系。任何医生都可以有很多约会,反之亦然。我还想在顶部实现 Automapper 映射。
高级模型结构
**医生** - ID - 姓名 - 约会
**预约** - ID - 姓名 - 类别 - 医生
医生模型
[Table("Doctors")]
public class Doctor
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<DoctorAppointment> Appointments { get; set; }
public Doctor()
{
Appointments = new Collection<DoctorAppointment>();
}
}
约会模式
[Table("Appointments")]
public class Appointment
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public ICollection<DoctorAppointment> Doctors { get; set; }
public Appointment()
{
Doctors = new Collection<DoctorAppointment>();
}
}
多对多医生-预约链接表
[Table("DoctorAppointments")]
public class DoctorAppointment
{
public int DoctorId { get; set; }
public int AppointmentId { get; set; }
public Doctor Doctor { get; set; }
public Appointment Appointment { get; set; }
}
数据库上下文
public class MyDocDbContext : DbContext
{
public DbSet<Appointment> Appointments { get; set; }
public DbSet<Doctor> Doctors { get; set; }
public MyDocDbContext(DbContextOptions<MyDocDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<DoctorAppointment>().HasKey(da =>
new { da.DoctorId, da.AppointmentId });
modelBuilder.Entity<DoctorAppointment>()
.HasOne(da => da.Doctor)
.WithMany(p => p.Appointments)
.HasForeignKey(pt => pt.DoctorId);
modelBuilder.Entity<DoctorAppointment>()
.HasOne(pt => pt.Appointment)
.WithMany(t => t.Doctors)
.HasForeignKey(pt => pt.AppointmentId);
}
}
医生和预约控制人:
[HttpGet("appointment/{id}")]
public async Task<IActionResult> GetAppointment(int id)
{
var app = await context.Appointments
.Include(a => a.Doctors)
.ThenInclude(da => da.Doctor)
.SingleOrDefaultAsync(a => a.Id == id);
return Ok(app);
}
[HttpGet("doctor/{id}")]
public async Task<IActionResult> GetDoctor(int id)
{
var doc = await context.Doctors
.Include(d => d.Appointments)
.ThenInclude(da => da.Appointment)
.SingleOrDefaultAsync(v => v.Id == id);
return Ok(doc);
}
现在实现Automapper 资源映射...
到此为止,一切正常,因为在获取这两个实体时,它会返回所有关系。使用 Automapper 将域映射到 API 资源时会出现问题。使用以下映射资源:
博士资源
public class DoctorResource
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<AppointmentResource> Appointments { get; set; }
public DoctorResource()
{
Appointments = new Collection<AppointmentResource>();
}
}
预约资源
public class AppointmentResource
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public ICollection<DoctorResource> Doctors { get; set; }
public AppointmentResource()
{
Doctors = new Collection<DoctorResource>();
}
}
最后,映射如下:
public class MappingProfile : Profile
{
public MappingProfile()
{
// Domain to API Resource
CreateMap<Doctor, DoctorResource>()
.ForMember(dr => dr.Appointments, opt => opt
.MapFrom(d => d.Appointments
.Select(y => y.Appointment)
.ToList()));
CreateMap<Appointment, AppointmentResource>()
.ForMember(dr => dr.Doctors, opt => opt
.MapFrom(d => d.Doctors
.Select(y => y.Doctor)
.ToList()));
}
}
因此,当不使用映射资源时,JSON 结果是这样的(想要的):
**http://localhost:5000/api/appointment/1**
{
"id": 1,
"name": "Personal Trainer",
"category": "Fitness",
"doctors": [
{
"doctorId": 2027,
"appointmentId": 1,
"doctor": {
"id": 2027,
"name": "Dr. Cunha",
"appointments": [],
}
},
{
"doctorId": 2028,
"appointmentId": 1,
"doctor": {
"id": 2028,
"name": "Dr. Gouveia",
"appointments": [],
}
},
{
"doctorId": 2029,
"appointmentId": 1,
"doctor": {
"id": 2029,
"name": "Dr. Tiago",
"appointments": [],
}
}
]
}
但是,当使用 Automapper 映射API 响应时,它会再次扩展 Appointments 类别和 Doctors ,依此类推......
**http://localhost:5000/api/appointment/1**
{
"id": 1,
"name": "Personal Trainer",
"category": "Fitness",
"doctors": [
{
"id": 2027,
"name": "Dr. Cunha",
"appointments": [
{
"id": 1,
"name": "Personal Trainer",
"category": "Fitness",
"doctors": [
{
"id": 2028,
"name": "Dr. Gouveia",
"appointments": [
{
"id": 1,
"name": "Personal Trainer",
"category": "Fitness",
"doctors": [
{ ....
and so on...
然而,出于某种未知的原因,Doctor Controller会返回所需的输出。
很抱歉这篇冗长的帖子,但我无法在不暴露整个内容的情况下为您提供清晰的图片。
干杯
解决方案
我假设你的 MappingProfile 应该像下面这样改变:
public MappingProfile()
{
// Domain to API Resource
CreateMap<Doctor, DoctorResource>()
.ForMember(dr => dr.Appointments, opt => opt
.MapFrom(d => d.DoctorAppointment
.Select(y => y.Appointment)
.ToList()));
CreateMap<Appointment, AppointmentResource>()
.ForMember(dr => dr.Doctors, opt => opt
.MapFrom(d => d.DoctorAppointment
.Select(y => y.Doctor)
.ToList()));
}
而不是 MapFrom(d => d.Doctors) 和 MapFrom(d => d.Appointments) 用 MapFrom(d => d.DoctorAppointment) 替换它们
它应该是工作。
推荐阅读
- java - 使用 Spring Boot API 编码时出现错误“java.util.NoSuchElementException: No value present”。请帮助检查并解决问题。谢谢
- java - Spring MVC 的 REST API 部署
- azure - Is there a way to use the TimeSeries Insights graphs in your website?
- c# - 有什么方法可以检测到返回类型为 void 的 flood_fill 递归方法的结束?
- node.js - MERN Stack: User ID returns null on POST
- c - 关于二维矩阵线性化的问题
- android - 如何通过 ViewModel 从 Fragment 观察 Repository LiveData
- typo3 - TYPO3:为 1 页修改 TSConfig 不适用于 cs_seo
- mysql - MySQL 高级排序结合两个查询
- node.js - 如何用凹度绘制文字