EF Core - 将实体映射到自定义类会引发循环引用的堆栈溢出



我正在用 asp.net 核心webapi构建一个API POC。我正在尝试将 EF Core 实体与 API 返回的对象分开,以便我可以针对不同的方法自定义它们。

为了实现这一点,我创建了将实体映射到的自定义类。当我尝试映射具有一对多或多对多关系的实体(EF Core 中中间实体的 2 倍一对多)时,这会崩溃

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; }
}

用于映射国家/地区实体的 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 方面包含国家/地区。像这样构建我的类可以解决问题,但是我必须在关系的每一侧创建一个额外的类(区域一侧的区域国家,它映射国家)。我想做的是在"一个国家有很多用户。用户有一个国家。我必须创建一个具有 Users 集合的国家/地区类和一个无法在用户和国家/地区端映射它的国家/地区类,而直观地这两个类本身应该足够了......这是否有意义?

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;
}
}

最新更新