我对 EF core 和 C# 总体来说还很陌生。 我试图了解如何从 EF core 为我制作的中间表进行正确的查询。
public class Device
{
public Guid Id {get ; set;}
public string Model { get; set; }
public string Description { get; set; }
public int Release_Year { get; set; }
public double RentPrice { get; set; }
public double PurchasePrice { get; set; }
public ICollection<Category>? DeviceCategory { get; set; } = default!;
public Guid AppUserId { get; set; }
public AppUser? AppUser { get; set; }
}
public class Category
{
public Guid Id {get ; set;}
public string Name { get; set; }
public Guid AppUserId { get; set; }
public AppUser? AppUser { get; set; }
}
下面我附上了迁移和创建数据库后为我制作的 ERD 和 EF 核心
所以现在我试图获取设备并从我的API控制器附加设备所属的所有类别,但我有点困惑如何做到这一点,因为我没有CategoryDevice表的数据库集。
// GET: api/Devices/5
[HttpGet("{id}")]
public async Task<ActionResult<Device>> GetDevice(Guid id)
{
var device = await _context.Devices.FindAsync(id);
if (device == null)
{
return NotFound();
}
return device;
}
目前,如果我尝试发出 GET 请求,我的 deviceCategory 为空 { “型号”:“索尼相机”, “描述”:“很酷的相机”, “发布年份”:2055, “租金价格”:33.23, “购买价格”:55.3, “设备类别”:空, “appUserId”:“155f58bb-bd41-4213-9ea0-5a7fc0847ebc”, “应用程序用户”:空, “id”:“31d1d653-88ff-4f57-a05c-dfb6a9768291” },
默认情况下,EF core 不会从数据库中获取相关实体。如果您还想获取主要实体和相关实体,则需要要求 EF core 来执行此操作。 有多种方法和模式可以做到这一点,您可以在此处找到有关此主题的更多信息。
加载相关实体的最简单模式是急切加载方法,当您从数据库中获取主实体时,您会急切地加载相关实体。这将导致一个包含一个或多个连接的数据库查询。
在您的情况下,如果您想使用急切加载方法,可以这样做:
var device = await _context
.Devices
.Include(x => x.DeviceCategory)
.FirstOrDefaultAsync(id);
这里可能的改进点是定义仅在表示层中使用的正确数据传输对象,并使用要向 API 客户端公开的最少数据量。这样,您可以避免将实体直接暴露给消费者,并且可以解耦域模型和表示层。随着时间的推移,这将使维护变得更加容易。
这是这种方法的一个例子:
public sealed class CategoryDto
{
public string Name { get; init; }
}
public sealed class DeviceDto
{
public Guid Id {get ; init;}
public string Model { get; init; }
public string Description { get; init; }
public IReadOnlyList<CategoryDto> Categories { get; init; } = new List<CategoryDto>();
}
var device = await _context
.Devices
.Select(d => new DeviceDto
{
Id = d.Id,
Model = d.Model,
Description = d.Description,
Categories = d.Categories.Select(c => new CategoryDto
{
Name = c.Name
}).ToList()
})
.FirstOrDefaultAsync(id);