jeudi 25 juillet 2019

EF Core - Mapping entities to custom classes throws stackoverflow for cyclic references

I'm building an API POC with asp.net core webapi. I'm trying to separate the EF Core entities from the objects returned by the API so I can customise them for different methods.

To achieve this I've created custom classes to which I map the entities. This breaks down when I'm trying to map Entities having one-to-many or many-to-many relations (2x one-to-many with an intermediary entity in EF Core)

EF Core Entities

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-side custom class example for mapping the Country entity

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 => new CountryRegion(cr.Region)).ToList();
    }
  }

  public static implicit operator Country(Database.Models.Country country)
  {
    return country != null ? new Country(country) : null;
  }
}

Everything works fine EF-wise, but evidently, when executing this mapping, EF entities will just cycle through the relation and end up throwing a StackOverflowException.

I am almost convinced I am approaching this the wrong way. Is there maybe a pattern that already solves this issue that I've overlooked?

Aucun commentaire:

Enregistrer un commentaire