我目前正在使用API,遇到了一个与实体序列化相关的问题。我有一个Car类,它引用了其他类,其中一些类包含它们自己的区域设置,例如Color和Transmission。
下面是我的Car类的结构:
public class Car : IEntity
{
public int Id { get; set; }
public int? OwnerId { get; set; }
public int BrandId { get; set; }
public int ModelId { get; set; }
public int ReleaseYearId { get; set; }
public int ColorId { get; set; }
public int MarketId { get; set; }
public int? RegionId { get; set; }
public int GearTypeId { get; set; }
public int CategoryId { get; set; }
public int FueltypeId { get; set; }
public int CurrencyId { get; set; }
public int? AutoSalonId { get; set; }
public int TransmissionId { get; set; }
public ushort EngineVolume { get; set; }
public ushort HorsePower { get; set; }
public DateTime LastUpdated { get; set; }
public string? Description { get; set; }
public int Mileage { get; set; }
public int MileageTypeId { get; set; }
public int Price { get; set; }
public ushort? SeatCount { get; set; }
public bool CreditAvailable { get; set; }
public bool BarterAvailable { get; set; }
public List<Image> Images { get; set; } = new();
public List<Feature> Features { get; set; } = new();
public User? Owner { get; set; }
public Brand? Brand { get; set; }
public Model? Model { get; set; }
public Year? Year { get; set; }
public Color? Color { get; set; }
public Region? Region { get; set; }
public Market? Market { get; set; }
public GearType? GearType { get; set; }
public Category? Category { get; set; }
public FuelType? Fueltype { get; set; }
public Currency? Currency { get; set; }
public MileageType? MileageType { get; set; }
public Transmission? Transmission { get; set; }
public AutoSalon? AutoSalon { get; set; }
public Car() { }
}
字符串
我的Color和Transmission类的结构如下:
public class Color : IEntity
{
public int Id { get; set; }
public List<ColorLocale>? ColorLocales { get; set; }
public Color() { }
}
public class ColorLocale : IEntity
{
public int Id { get; set; }
public int LanguageId { get; set; }
public string Name { get; set; } = string.Empty;
public Color? Color { get; set; }
public Language? Language { get; set; }
public ColorLocale() { }
}
public class Transmission : IEntity
{
public int Id { get; set; }
public List<TransmissionLocale>? TransmissionLocales { get; set; }
public Transmission() { }
}
public class TransmissionLocale : IEntity
{
public int Id { get; set; }
public int LanguageId { get; set; }
public string Name { get; set; } = string.Empty;
public Language? Language { get; set; }
public Transmission? Transmission { get; set; }
public TransmissionLocale() { }
}
型
当我试图从我的数据库(我已经确认是在那里,因为我已经调试它),并返回它从我的控制器,该进程似乎挂起,由于序列化没有完成。
以下是我的控制器的相关部分:
[HttpPost("getcars")]
public async Task<ActionResult<List<Car>>> GetCars(int pageNumber = 1, int pageSize = 20)
{
var carList = await _carService.GetCarsWithPagination("", pageNumber, pageSize);
return carList;
}
型
我尝试过几种方法来解决这个问题,比如将Newtonsoft的ReferenceLoopHandling设置为Ignore,或者将JsonSerializerOptions.ReferenceHandler设置为Preserve,但都没有成功:
builder.Services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
builder.Services.AddControllersWithViews().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
});
型
我想知道是否有人以前遇到过这个问题,并提供了一个解决方案。是否有任何其他设置,我可以调整或替代的方式来构建我的类,以避免这个问题?
任何帮助都非常感谢。
谢谢你,谢谢
1条答案
按热度按时间yqyhoc1h1#
最好的方法是 * 不 * 尝试序列化实体。实体用作数据域表示,不适合数据传输。将这些关注点分开,构造一个DTO来表示您实际想要发送的数据结构,然后使用EF将实体投影到该DTO。像Automapper这样的Map器有钩子通过
ProjectTo<TDTO>()
与EF的IQueryable
一起工作,以构建高效的查询来填充这些类,而无需将整个实体图加载到内存中。如果您将DTO带回以更新实体,则可以使用Map(src, dest)
方法将允许的值复制回新加载的实体。当涉及到实体本身时,我建议默认使用单向引用,而不是双向引用。尝试做类似序列化实体的事情的一个问题是,其中Transmission具有对一个或多个TransmissionLocale的引用,这些TransmissionLocale具有对Transmission的引用。同样,我不建议为了数据传输而序列化实体,但是经常有这样的情况,我确实想序列化实体,比如记录所讨论的实体的快照,比如记录异常时,或者记录审计日志快照。在大多数情况下,这些引用是不必要的,并且可以减少/消除序列化陷入循环的情况。在大多数情况下,使用单向引用可以很好地解决查询。例如,如果您希望所有传输都用于特定区域设置:
双向:
字符串
单向:
型
就我个人而言,我发现使用单向引用更直接,因为当选择特定类型的实体时,我会去他们的DbSet,而不是链接表,如果我得到与特定顶级实体相关的项目,我会通过该顶级实体。例如,如果我希望所有汽车都具有特定区域的变速器:
型
通常情况下,条件可以通过AND或OR跨关注点组合,因此如果我正在寻找汽车,我希望从汽车查询到汽车的组成部分,以便我可以组合条件,而不是试图从查询其组件中选择汽车。例如,如果我想要一辆带有特定区域的变速器或齿轮类型的汽车。