Home > Back-end >  ASP.NET Core / EF Core 6: dbContext.saveChanges() produces stack overflow error
ASP.NET Core / EF Core 6: dbContext.saveChanges() produces stack overflow error

Time:05-21

Getting "stack overflow" error when saving data to dbContext.saveChanges()

Stack overflow.
Repeat 87208 times:
--------------------------------
   at WebAPI.Models.WorkProfile..ctor()
   at WebAPI.Models.WorkAccount..ctor()
--------------------------------
   at DynamicClass..ctor()
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnTryRead(System.Text.Json.Utf8JsonReader ByRef, System.Type, System.Text.Json.JsonSerializerOptions, System.Text.Json.ReadStack ByRef, System.__Canon ByRef)
   at System.Text.Json.Serialization.JsonConverter`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryRead(System.Text.Json.Utf8JsonReader ByRef, System.Type, System.Text.Json.JsonSerializerOptions, System.Text.Json.ReadStack ByRef, System.__Canon ByRef)
   at System.Text.Json.Serialization.JsonConverter`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCore(System.Text.Json.Utf8JsonReader ByRef, System.Text.Json.JsonSerializerOptions, System.Text.Json.ReadStack ByRef)
   at System.Text.Json.Serialization.JsonConverter`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadCoreAsObject(System.Text.Json.Utf8JsonReader ByRef, System.Text.Json.JsonSerializerOptions, System.Text.Json.ReadStack ByRef)
etc. 
etc. 
etc..........

This is my controller:

[HttpPost]
[Consumes("application/json")]
public async Task<ActionResult<WorkAccount>> Post(WorkAccount workAccount)
{
    if (Request.HasJsonContentType())
    {
        // this runs: logs out JSONcontent.
        Console.WriteLine("JSON content");
    }
    else
    {
        Console.WriteLine("NO json!");
    }

    _context.WorkAccounts.Add(workAccount);
    await _context.SaveChangesAsync();

    return CreatedAtAction("GetTodoItem", workAccount);
}

And these are my model classes:

public class WorkAccount : BaseDateEntity
{
    public int WorkAccountId { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public WorkProfile? WorkProfile { get; set; } = new WorkProfile();
}

public class WorkProfile : BaseDateEntity
{
    public int WorkProfileId { get; set; }
    public int WorkAccountId { get; set; }
    public List<Booking> Bookings { get; set; } = new List<Booking>();
    public List<Advert> Adverts { get; set; } = new List<Advert>();
    public List<WorkProfileLanguage> WorkProfileLanguages { get; set; } = new List<WorkProfileLanguage>();
    public WorkAccount WorkAccount { get; set; } = new WorkAccount();
}

// and some more models...

FluentAPI configuration

public class WorkAccountConfig : IEntityTypeConfiguration<WorkAccount>
{
    public void Configure(EntityTypeBuilder<WorkAccount> modelBuilder)
    {
        modelBuilder
        .HasOne(x => x.WorkProfile)
        .WithOne(y => y.WorkAccount)
        .HasForeignKey<WorkProfile>(z => z.WorkAccountId);
    }
}

Before this error, I had an another error. My WorkProfile navigation property looked like: public WorkProfile? WorkProfile { get; set; } without the = new WorkProfile() initialization and that produced the following error:

System.NullReferenceException: Object reference not set to an instance of an object.

I have also tried just returning the JSON data and it produces no errors and valid json.

public async Task<ActionResult<WorkAccount>> Post(WorkAccount workAccount)
{
    return workAccount;
}

The console.log output at chrome developer tools.

{
    "workAccountId": 0,
    "email": "mail here",
    "password": "boo",
    "workProfile": null,
    "createdAt": "0001-01-01T00:00:00",
    "updatedAt": "0001-01-01T00:00:00"
}

I am stuck. Does anyone know what could be wrong?

CodePudding user response:

Any time either WorkAccount or WorkProfile is instantiated you will create an infinite loop because WorkAccount creates a new default WorkProfile which creates a new default WorkAccount which creates a new WorkProfile

I would suggest removing those default instances.

You can get this same behavior just by trying to instantiate one of these.

    using System;

    public class Program
    {
        public static void Main()
        {
            var w = new WorkAccount();
        }

        public class WorkAccount 
        {
            public int WorkAccountId { get; set; }
            public string Email { get; set; }
            public string Password { get; set; }
            public WorkProfile? WorkProfile { get; set; } = new WorkProfile();
        }

        public class WorkProfile 
        {
            public int WorkProfileId { get; set; }
            public int WorkAccountId { get; set; }
            public WorkAccount WorkAccount { get; set; } = new WorkAccount();
        }

    }

The above will result in

Stack overflow.
Repeat 130975 times:
--------------------------------
   at Program WorkProfile..ctor()
   at Program WorkAccount..ctor()
--------------------------------
   at Program.Main()
Command terminated by signal 6

Removing the default instances runs without issue.

    using System;

    public class Program
    {
        public static void Main()
        {
            var w = new WorkAccount();
        }

        public class WorkAccount 
        {
            public int WorkAccountId { get; set; }
            public string Email { get; set; }
            public string Password { get; set; }
            public WorkProfile? WorkProfile { get; set; }
        }

        public class WorkProfile 
        {
            public int WorkProfileId { get; set; }
            public int WorkAccountId { get; set; }
            public WorkAccount WorkAccount { get; set; }
        }

    }
  • Related