unairoldan
unairoldan

Reputation: 2863

EF7 beta6: Error saving multiple entities

I am creating an API using ASP.NET5 and Entity Framework 7.0.0-beta 6, and when I try to execute various updates in several requests, I get this Exception:

'Company' cannot be tracked because another instance of this type with the same key is already being tracked. For new entities consider using an IIdentityGenerator to generate unique key values.

This is my code:

public class MrBellhopContext : DbContext
{

    public DbSet<Company> Company { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Company>(entity =>
        {
            entity.Key(c => c.CompanyId);

            entity.Index(c => c.Name);

            entity.Property(c => c.CompanyId).ValueGeneratedOnAdd();
        });

        modelBuilder.UseSqlServerIdentityColumns();

        base.OnModelCreating(modelBuilder);
    }

}


public class Company
{

    public int CompanyId { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public string Phone { get; set; }

    public string Email { get; set; }

    public short StatusId { get; set; }

}


public class CompanyRepository : ICompanyRepository
{

    MrBellhopContext _dbcontext;


    public async Task UpdateAsync(Company company)
    {
        _dbcontext.Update(company);
        await _dbcontext.SaveChangesAsync();
    }
}



[Route("api/[controller]")]
public class CompanyController : Controller
{


    [HttpPut]
    public async void UpdateAsync([FromBody] Company company)
    {
        if ((!ModelState.IsValid) || (company == null))
        {
            Context.Response.StatusCode = 400;
            return;
        }
        else
        {
            await _repository.UpdateAsync(company);
        }
    }

}

I have tried to solve it by removing ValueGeneratedOnAdd(), UseSqlServerIdentityColumns() or changing the mapping, but if I try to update several entities in several requests, I get the Exception:

  1. First req: Update CompanyId 8
  2. First req: Update CompanyId 9 !! ERROR

Does anyone know how to solve this issue?

Upvotes: 3

Views: 3438

Answers (3)

RahulSabharwal
RahulSabharwal

Reputation: 106

Even I was facing the same issue.

I was registering the Repositories as singleton in Configure method of startup.cs file. Changing that to AddScoped fixed the issue.

Just need to use the below code to update the records

_dbContext.Company.Update(company);
_dbContext.SaveChanges();

Upvotes: 0

unairoldan
unairoldan

Reputation: 2863

Resolved: https://github.com/aspnet/EntityFramework/issues/2652

I was adding Repository as a Singleton:

services.AddSigleton<Data.Interfaces.Company.ICompanyRepository,Data.Repositories.Company.CompanyRepository>();

This means that all requests are sharing a single instance of the repository. You should reduce this to Scoped, so that you have a single repository instance per request. Aside from avoiding the issue you are hitting, it will also ensure you don't end up with a gigantic context instance tracking all the data from your database in memory.

To solve:

services.AddScoped<Data.Interfaces.Company.ICompanyRepository,Data.Repositories.Company.CompanyRepository>();

Upvotes: 11

natemcmaster
natemcmaster

Reputation: 26773

You are getting this error because your instance of _repository already has an instance of Company in memory with the same key. This can happen when you are reusing an instance of DbContext across threads. Your sample above doesn't include the code about how CompanyController._repository gets instantiated. Make sure this is not shared between HTTP requests.

Also, put this line before you configure the key.

entity.Property(c => c.CompanyId).ValueGeneratedOnAdd();

Upvotes: 2

Related Questions