简体   繁体   中英

EF Core Many To Many. Error returning entities

I'm implementing an WebAPI using dotnet core (2) and EF Core. The application uses UnitOfWork/Repository-pattern. I've come to a point where I need to implement a "Many-To-Many"-relation but I'm having some trouble. This is what I've got sofar:

Entities:

public class Team : DataEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int TeamId { get; set; }

    public int OrganizationID { get; set; }

    public string Name { get; set; }

    public string URL { get; set; }

    public virtual ICollection<Season> Seasons { get; set; }

    public ICollection<TeamMember> TeamMember { get; set; }

}



public class Member : DataEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int MemberId { get; set; }

    public string Name { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string MobilePhone { get; set; }

    public string Email { get; set; }

    public int RelatedTo { get; set; }

    public int TeamRole { get; set; }

    public ICollection<TeamMember> TeamMember { get; set; }
}



public class TeamMember
{
    public int TeamId { get; set; }
    public Team Team { get; set; }

    public int MemberId { get; set; }
    public Member Member { get; set; }
}

In my DbContext-class:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<TeamMember>()
        .HasKey(t => new { t.TeamId, t.MemberId });

    modelBuilder.Entity<TeamMember>()
        .HasOne(tm => tm.Team)
        .WithMany(t => t.TeamMember)
        .HasForeignKey(tm => tm.TeamId);

    modelBuilder.Entity<TeamMember>()
        .HasOne(tm => tm.Member)
        .WithMany(t => t.TeamMember)
        .HasForeignKey(tm => tm.MemberId);

}

On my repository I have en extension for IncludeAll:

public static IQueryable<Team> IncludeAll(this IGenericRepository<Team> repository)
{
    return repository
        .AsQueryable()
        .Include(s => s.Seasons)
        .Include(tm => tm.TeamMember);

}

Everything builds as expected but when trying to invoke the controller-action that's fetching a Team (which I expect to include all members) or a Member (which I expect to include all the members teams - code not included above). SwaggerUI returns: TypeError: Failed to fetch. If I try to invoke the controller-action directly in chrome ( http://localhost/api/Team/1 ) i get an incomplete result, but never the less...a result :) :

{
    "value":
    {   
        "teamId":1,
        "organizationID":1,
        "name":"Team1",
        "url":"http://www.team1.com",
        "seasons":[
            {
                "id":1,
                "teamID":1,
                "name":"PK4",
                "description":null,
                "startDate":"2017-09-01T00:00:00",
                "endDate":"2018-12-31T00:00:00",
                "created":"2017-12-01T00:00:00",
                "updated":"2017-12-27T00:00:00",
                "createdBy":"magnus",
                "updatedBy":"magnus"
            }],
        "teamMember":[
            {
                "teamId":1

Am I missing something obvious?

You have a reference loop in your data structure (team -> team member -> team), and the JSON encoder can't deal with this.

I can think of two ways to solve this:

  • Configure the JSON encoder to ignore reference loops

In Startup.cs , add this:

services
    .AddMvc()
    .AddJsonOptions(options => {
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });

From the documentation :

ReferenceLoopHandling.Ignore : Json.NET will ignore objects in reference loops and not serialize them. The first time an object is encountered it will be serialized as usual but if the object is encountered as a child object of itself the serializer will skip serializing it.

  • Add the [JsonIgnore] attribute to the property you want to ignore

For example:

public class TeamMember
{
    public int TeamId { get; set; }
    [JsonIgnore]
    public Team Team { get; set; }
}

Might be related to some circular reference issue?!

your teamMember property has an Team property which again has a teamMember properties and so on... When trying to serialize, a never ending loop would be created.

Maybe you can set the teamMember.Team property to null. I think you would also have to set the teamMember.Member.teamMember property to null.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM