EF7 beta6: ошибка при сохранении нескольких сущностей

Я создаю API, используя ASP.NET5 и Entity Framework 7.0.0-beta 6, и когда я пытаюсь выполнить различные обновления в нескольких запросах, я получаю это исключение:

"Компания" не может быть отслежена, так как другой экземпляр этого типа с тем же ключом уже отслеживается. Для новых сущностей рассмотрите возможность использования IIdentityGenerator для создания уникальных значений ключа.

Это мой код:

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);
        }
    }

}

Я попытался решить эту проблему, удалив ValueGeneratedOnAdd(), UseSqlServerIdentityColumns() или изменив сопоставление, но если я попытаюсь обновить несколько объектов в нескольких запросах, я получаю исключение :

  1. Первое требование: обновить CompanyId 8
  2. Первое требование: обновить CompanyId 9 !! ОШИБКА

Кто-нибудь знает, как решить эту проблему?


person unairoldan    schedule 13.07.2015    source источник
comment
Пробовали добавить атрибут [Key] к свойству первичного ключа, которое в вашем случае ComapnyId?   -  person believe me    schedule 13.07.2015
comment
ошибка говорит о том, что у вас есть два экземпляра Company с одинаковым идентификатором. Судя по вашему коду, это не так, но я не уверен. Можете ли вы показать вызывающий объект UpdateAsync ?   -  person Bart Calixto    schedule 15.07.2015
comment
@ Барт Да, конечно. Включаю код.   -  person unairoldan    schedule 15.07.2015
comment
Я думаю, что есть что-то, что еще живо в DBContext после выполнения первой операции; и когда я выполняю второй, происходит сбой   -  person unairoldan    schedule 15.07.2015


Ответы (3)


Решено: https://github.com/aspnet/EntityFramework/issues/2652.

Я добавлял репозиторий как синглтон:

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

Это означает, что все запросы используют один и тот же экземпляр репозитория. Вы должны уменьшить это значение до Scoped, чтобы у вас был один экземпляр репозитория для каждого запроса. Помимо предотвращения проблемы, с которой вы сталкиваетесь, это также гарантирует, что вы не получите гигантский экземпляр контекста, отслеживающий все данные из вашей базы данных в памяти.

Решать:

services.AddScoped<Data.Interfaces.Company.ICompanyRepository,Data.Repositories.Company.CompanyRepository>();
person unairoldan    schedule 05.08.2015
comment
Это исправило это для меня в ASP 5 vNext с EF 7 - person Coaden; 02.04.2016
comment
@natemcmaster уже дал ответ, в котором объяснялась проблема и предлагалось решение. Возможно, вы могли бы указать его ответ, помимо предоставления своего решения для будущих читателей. - person superjos; 18.08.2016

Вы получаете эту ошибку, потому что у вашего экземпляра _repository уже есть экземпляр Company в памяти с тем же ключом. Это может произойти при повторном использовании экземпляра DbContext в потоках. В приведенном выше примере нет кода о том, как создается экземпляр CompanyController._repository. Убедитесь, что это не используется совместно HTTP-запросами.

Кроме того, поместите эту строку перед настройкой ключа.

entity.Property(c => c.CompanyId).ValueGeneratedOnAdd();
person natemcmaster    schedule 29.07.2015

Даже я столкнулся с той же проблемой.

Я регистрировал репозитории как singleton в методе Configure файла startup.cs. Изменение этого на AddScoped устранило проблему.

Просто нужно использовать приведенный ниже код для обновления записей

_dbContext.Company.Update(company);
_dbContext.SaveChanges();
person RahulSabharwal    schedule 21.11.2016