c# - EF Core - 将实体映射到自定义类会引发循环引用的 stackoverflow
问题描述
我正在使用 asp.net core webapi 构建一个 API POC。我正在尝试将 EF Core 实体与 API 返回的对象分开,以便为不同的方法自定义它们。
为了实现这一点,我创建了将实体映射到的自定义类。当我尝试映射具有一对多或多对多关系的实体时(2x 一对多与 EF Core 中的中间实体),这会崩溃
EF 核心实体
public class Country
{
[Key]
public string Code { get; set; }
public string Name { get; set; }
// Relations
public virtual ICollection<CountryRegion> CountryRegions { get; set; }
}
public class Region
{
[Key]
public string Code { get; set; }
public string Name { get; set; }
// Relations
public virtual ICollection<CountryRegion> CountryRegions { get; set; }
}
public class CountryRegion
{
public string CountryCode { get; set; }
public virtual Country Country { get; set; }
public string RegionCode { get; set; }
public virtual Region Region { get; set; }
}
用于映射 Country 实体的 API 端自定义类示例
public class Country
{
public string Code { get; set; }
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IList<CountryRegion> Regions { get; set; }
public Country() { }
public Country(Database.Models.Country country)
{
this.Code = country.Code;
this.Name = country.Name;
if (country.CountryRegions != null)
{
this.Regions = country.CountryRegions.Select(cr => new CountryRegion(cr.Region)).ToList();
}
}
public static implicit operator Country(Database.Models.Country country)
{
return country != null ? new Country(country) : null;
}
}
按照 Ivan Stoev 的建议,从 API 端包含 CountryRegion。像这样构建我的类可以解决问题,但是我必须在关系的每一侧创建一个额外的类(区域侧的 RegionCountry,它映射国家)。我试图做的是避免这种情况,例如“一个国家有很多用户。一个用户有一个国家”。我必须创建一个 Country 类,该类具有 Users 集合,而一个不能在 User 和 Country 端映射它的类,直觉上这两个类本身就足够了……如果这有意义吗?
public class CountryRegion
{
public string Code { get; set; }
public string Name { get; set; }
public CountryRegion() { }
public CountryRegion(Database.Models.Region region)
{
this.Code = region.Code;
this.Name = region.Name;
}
public static implicit operator CountryRegion(Database.Models.Region region)
{
return region != null ? new CountryRegion(region) : null;
}
}
EF 方面一切正常,但显然,在执行此映射时,EF 实体只会循环遍历关系并最终抛出StackOverflowException
.
我几乎确信我正在以错误的方式处理这个问题。是否有一种模式已经解决了我忽略的这个问题?
解决方案
好的,所以我设法通过仅删除循环引用来解决需要卫星类来投射关系的每一端。这行得通,但我仍然觉得这有点尴尬,并从设计模式的角度提出了更多问题,也许有更优雅的方式来做到这一点?
public class Country
{
public string Code { get; set; }
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IList<Region> Regions { get; set; }
public Country() { }
public Country(Database.Models.Country country)
{
this.Code = country.Code;
this.Name = country.Name;
if (country.CountryRegions != null)
{
this.Regions = country.CountryRegions
.Select(cr => { cr.Region.CountryRegions = null; return new Region(cr.Region); })
.ToList();
}
}
public static explicit operator Country(Database.Models.Country country)
{
return country != null ? new Country(country) : null;
}
}
public class Region
{
public string Code { get; set; }
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IList<Country> Countries { get; set; }
public Region() { }
public Region(Database.Models.Region region)
{
this.Code = region.Code;
this.Name = region.Name;
if (region.CountryRegions != null)
{
this.Countries = region.CountryRegions
.Select(cr => { cr.Country.CountryRegions = null; return new Country(cr.Country); })
.ToList();
}
}
public static explicit operator Region(Database.Models.Region region)
{
return region != null ? new Region(region) : null;
}
}
推荐阅读
- object - 如何查看对象数组中的特定属性
- text-to-speech - 使用时不需要的暂停
用于 TTS 的 SSML 中的标记 - python - 替换选择数据框列(基于其他条件)问题
- javascript - 安装 material-ui v3.0.3 时 JSON 输入文件意外结束
- c - 如何优化从输入中读取字符,以便用户无需事先指定字符数
- java - 通过传递用户 ID 列表更新多个用户
- java - “com.fasterxml.jackson.databind.JsonMappingException:预期类型为浮点数、整数或字符串。” 使用 ObjectMapper 转换 java.time.Instant
- java - 具有多个输入数字和运算符的命令行计算器?
- python - 如何使用乌龟将图形放在一个圆圈内?
- spring - spring boot 2.x kebab-case 格式的问题