C# EF Core-将实体映射到自定义类会引发循环引用的stackoverflow

C# EF Core-将实体映射到自定义类会引发循环引用的stackoverflow,c#,asp.net-web-api,design-patterns,entity-framework-core,C#,Asp.net Web Api,Design Patterns,Entity Framework Core,我正在用asp.net核心webapi构建一个API POC。我试图将EF核心实体与API返回的对象分开,以便为不同的方法定制它们 为了实现这一点,我创建了将实体映射到的自定义类。当我试图映射具有一对多或多对多关系的实体时(EF Core中有一个中间实体的2x一对多关系),就会出现这种情况 EF核心实体 公共类国家 { [关键] 公共字符串代码{get;set;} 公共字符串名称{get;set;} //关系 公共虚拟ICollection CountryRegions{get;set;} }

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

为了实现这一点,我创建了将实体映射到的自定义类。当我试图映射具有一对多或多对多关系的实体时(EF Core中有一个中间实体的2x一对多关系),就会出现这种情况

EF核心实体

公共类国家
{
[关键]
公共字符串代码{get;set;}
公共字符串名称{get;set;}
//关系
公共虚拟ICollection CountryRegions{get;set;}
}
公共类区域
{
[关键]
公共字符串代码{get;set;}
公共字符串名称{get;set;}
//关系
公共虚拟ICollection CountryRegions{get;set;}
}
公共类CountryRegion
{
公共字符串CountryCode{get;set;}
公共虚拟国家{get;set;}
公共字符串区域码{get;set;}
公共虚拟区域{get;set;}
}
映射国家实体的API端自定义类示例

公共类国家
{
公共字符串代码{get;set;}
公共字符串名称{get;set;}
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
公共IList区域{get;set;}
公共国家({}
公共国家(Database.Models.Country)
{
this.Code=country.Code;
this.Name=country.Name;
如果(country.CountryRegions!=null)
{
this.Regions=country.CountryRegions.Select(cr=>newcountryregion(cr.Region)).ToList();
}
}
公共静态隐式运算符国家(Database.Models.Country)
{
返回国家!=null?新国家(国):null;
}
}
根据Ivan Stoev的建议,从API方面包括CountryRegion。这样构建类可以解决问题,但是我必须在关系的每一侧创建一个额外的类(RegionCountry位于region一侧,它映射国家)。我想做的是在“一个国家有很多用户,一个用户有一个国家”这样的情况下避免这种情况。我必须创建一个包含用户集合的国家级类,一个不能在用户和国家级同时映射的国家级类,直觉上这两个类本身就足够了。。。这有意义吗

公共类CountryRegion
{
公共字符串代码{get;set;}
公共字符串名称{get;set;}
公共CountryRegion(){}
公共国家地区(Database.Models.Region)
{
this.Code=region.Code;
this.Name=region.Name;
}
公共静态隐式运算符CountryRegion(Database.Models.Region)
{
返回地区!=null?新国家地区(地区):null;
}
}
一切在EF方面都很好,但很明显,在执行此映射时,EF实体只会在关系中循环,并最终抛出一个
StackOverflowException


我几乎确信我是以错误的方式处理这件事的。是否有一种模式已经解决了我忽略的这个问题?

好的,所以我设法通过删除循环引用来解决需要附属类来转换关系的每一端的问题。这是可行的,但我仍然觉得这有点尴尬,从设计模式的角度提出了更多的问题,也许有一种更优雅的方式来做到这一点

公共类国家
{
公共字符串代码{get;set;}
公共字符串名称{get;set;}
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
公共IList区域{get;set;}
公共国家({}
公共国家(Database.Models.Country)
{
this.Code=country.Code;
this.Name=country.Name;
如果(country.CountryRegions!=null)
{
this.Regions=country.CountryRegions
.Select(cr=>{cr.Region.CountryRegions=null;返回新区域(cr.Region);})
.ToList();
}
}
公共静态显式运算符国家(Database.Models.Country)
{
返回国家!=null?新国家(国):null;
}
}
公共类区域
{
公共字符串代码{get;set;}
公共字符串名称{get;set;}
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
公共IList国家{get;set;}
公共区域(){}
公共区域(Database.Models.Region)
{
this.Code=region.Code;
this.Name=region.Name;
如果(region.CountryRegions!=null)
{
this.Countries=region.CountryRegions
.Select(cr=>{cr.Country.CountryRegions=null;返回新国家(cr.Country);})
.ToList();
}
}
公共静态显式运算符区域(Database.Models.Region)
{
返回区域!=null?新区域(区域):null;
}
}

好的,所以我设法解决了需要附属类来转换关系两端的问题,只需删除循环引用。这是可行的,但我仍然觉得这有点尴尬,从设计模式的角度提出了更多的问题,也许有一种更优雅的方式来做到这一点

公共类国家
{
公共字符串代码{get;set;}
公共字符串名称{get;set;}
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
公共IList区域{get;set;}
公共国家({}
公共国家(Database.Models.Country)
{
this.Code=country.Code;
this.Name=country.Name;
如果(country.CountryRegions!=null)
{
this.Regions=country.CountryRegions
.Select(cr=>{cr.Region.CountryRegions=null;返回新区域(cr.Region);})
.ToList();
}
}
公共静态显式运算符国家(Database.Models.Country)
{
返回国家!=null?新国家(国):null;
}
}
公共类区域
{
公共字符串代码{get;set;}
公共字符串名称{get;set;}
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
聚氨基甲酸酯