A Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'operação de Banco de dados esperado para afectar 1 row(s), mas na verdade afetado 2 linha(s)

0

Pergunta

Recebi este erro uma vez que eu tente atualizar a tabela com o mesmo valor (carNumber), a minha condição é a atualização onde o retorno real campo de data é nulo.

Por alguma razão, é olhar como a consulta de retorno em 2 fileiras, mas na verdade existe apenas um. Eu estou usando EF. Esta é a função:

o erro - print screen

   public void updateStatus(int carNumber1, string acctualDate1)
    {
        DateTime accReturn = DateTime.Parse(acctualDate1);

        var orderCar1 =  db.CarRentalFields.FirstOrDefault(carNum =>
        (carNum.CarNumber == carNumber1 && carNum.ActualReturnDate == null));

            orderCar1.ActualReturnDate = accReturn  ;
             
                db.SaveChanges();

O erro de elevar ao tentar db.saveChanges()

a tabela do banco de dados, o número do carro é 1000 - print screen

modelBuilder.Entidade pic

por favor, deixe-me saber como eu posso resolver este problema.

c# entity-framework linq sql-server
2021-11-23 20:34:34
2
0

problema resolvido por adicionar uma nova coluna para o car_rental_fields tabela, coluna de id, que incluem a Identidade. como eu entendo, a partir daqui e da internet, há um problema complicado pk. em minha solução a id não é uma chave primária, mas é fazer a lógica para linq para atualizar a coluna correta. obrigado " para todas as pessoas envolvidas neste problema.

2021-11-26 20:37:27
0

Este erro ocorre quando a EF não é possível resolver o PK para a sua entidade. Na maioria dos casos, por entidades simples, EF convenções pode trabalhar fora do PK, mas no seu caso, você está usando uma chave composta, então isso precisa ser configurado. Dependendo de como você o mapeamento de suas entidades e você pode fazer isso em:

  • um EDMX
  • o DbContext.OnModelCreating
  • usando um EntityTypeConfiguration declaração
  • uso de atributos dentro da própria entidade

Desde que nós não sabemos como suas entidades são configurados, você pode verificar isso como a causa, usando o atributo de abordagem dentro de sua entidade como um teste. Se você estiver usando um EDMX as classes de entidade será gerado, então você vai querer substituir essa configuração dentro do EDMX. (Não pode realmente ajudá-lo lá, porque eu não uso o dang coisas :D )

Provavelmente você terá algo como:

public class CarRentalFields
{
    [Column("start_day")]
    public DateTime StartDay { get; set; }
    [Column("return_date")]
    public DateTime ReturnDate { get; set; }
    [Column("user_id")]
    public int UserId { get; set; }
    [Column("car_number")]
    public DateTime CarNumber { get; set; }
    
    // ... more columns...
}

Você pode até ter uma [Key] atributo em um desses campos, tais como CarNumber. Se há um PK mapeada na entidade o problema é que ele não é específico o suficiente para identificar exclusivamente a linha. Quando EF vai para a atualização de uma entidade, está a verificar, e esperar a atualização de apenas uma linha na tabela. Para encontrar mais do que uma linha será afetado de modo de falha.

Acrescentar os atributos para o [Key] com a ordem da coluna, por isso é reconhecida como uma chave composta.

public class CarRentalFields
{
    [Key, Column(Name="start_day", Order=1)]
    public DateTime StartDay { get; set; }
    [Key, Column(Name="return_date", Order=2)]
    public DateTime ReturnDate { get; set; }
    [Key, Column(Name="user_id", Order=3)]
    public int UserId { get; set; }
    [Key, Column(Name="car_number", Order=4)]
    public DateTime CarNumber { get; set; }
    
    // ... more columns...
}

Desde que estes 4 colunas são garantidos para ser uma restrição unique na tabela, EF será satisfeito quando apenas uma linha é actualizada quando ele cria é instrução SQL UPDATE.

Note novamente que se isso funcionar e você estiver usando um EDMX, você precisará revisar e modificar as suas EDMX mapeamento para fazer as alterações apropriadas, desde que a entidade de classe pode ser regenerado, perdendo seus atributos extra. (Eu acredito que o gerado classes de entidade a partir de um EDMX tem um comentário de cabeçalho de aviso de que é uma classe gerada, de modo que é um indicador a ter em atenção.)

Atualização: O meu principal suspeito seria que a tabela, na verdade, não têm uma correspondência PK definido, ou executar uma diferente PK combinação, ou mais provavelmente nenhum PK dada a natureza dos campos. EF pode operado em tabelas que não possuem PK definido, mas exige uma definição de Chave que garante registros pode ser identificado exclusivamente. O erro que você está vendo o que acontece quando a chave de definição não é exclusivo o suficiente. (I. e. se você estiver atualizando o carro 1, e a seleção de uma linha que tem: car_number = 1, start_day = 2021-11-21, return_day = 2021-11-22, user_id = 0 O problema é que, mais do que uma linha tem essa combinação de base de dados. Se a DB que você está verificando não ter mais de uma linha correspondente, em seguida, a sua aplicação é quase certamente, apontando para um banco de dados diferente do que está a verificar.

Coisas que você pode fazer para verificar isso:

  1. obter o tempo de execução de seqüência de caracteres de conexão e veja se ele combina a DB está a verificar:

Antes de executar a consulta, adicione o seguinte:

// EF6
var connectionString = db.Database.Connection.ConnectionString;
// EF Core 5
var connectionString = db.Database.GetConnectionString();
  1. Ter um olhar para os dados que são, na verdade, consultar:

.

var cars =  db.CarRentalFields.Where(carNum =>
    (carNum.CarNumber == carNumber1 && carNum.ActualReturnDate == null)).ToList();

Enquanto essa consulta pode retornar apenas 1 registro, que não é a causa do problema. O que você quer é o CarNumber, StartDate, ReturnDate, e a id de usuário para este registo:

var car =  db.CarRentalFields
    .Where(carNum => carNum.CarNumber == carNumber1 
        && carNum.ActualReturnDate == null)
    .Select(x => new 
    {
        x.CarNumber,
        x.StartDay,
        x.ReturnDate,
        x.UserId
    }).Single(); // Expect our 1 record here...
var cars = db.CarRentalFields
    .Where(x => x.CarNumber == car.CarNumber
        && x.StartDay == car.StartDay
        && x.ReturnDate == car.ReturnDate
        && x.UserId == car.UserId)
    .ToList(); // Get rows that match our returned Key fields.

Estas consultas selecione o assumido PK valores para o carro registro que você significa para atualização, em seguida, procura carros de registros coincidentes com a expectativa de campos-Chave. Meu dinheiro estaria em que, enquanto o topo consulta retorna 1 registo, o fundo consulta retorna duas linhas, o que significa, enquanto apenas 1 registo tem um #nulo ActualReturnDate valor, a sua Chave é não singular o suficiente para o conteúdo desta tabela.

2021-11-26 22:57:48

eu estou usando contex, você viu a minha impressão de tela de o construtor de modelo?
elirans

Sim, ok, é usar o DbContext do OnModelCreating modelBuilder, assim, a Chave está sendo definido. A próxima coisa a verificar é saber se as colunas correspondem a PK /w restrição unique em seu banco de dados correspondente. Se não, essa chave pode precisa ser expandido. Chaves compostas devem ser evitadas o máximo possível de como fazer a configuração de relações muito mais trabalho. Você também pode usar um profiler para capturar a proposta de instrução de atualização, em seguida, converta-a em uma simples ESCOLHA para ver quais linhas são retornadas. Por algum motivo mais do que uma linhas estão voltando.
Steve Py

Outra coisa a verificar é se no tempo de execução da aplicação é de bater o mesmo banco de dados que você está verificando. Os dados que você estiver verificando pode parecer singular o suficiente se o DB não é impor uma restrição exclusiva sobre as colunas, mas o banco de dados que está sendo apontada em tempo de execução tem linhas duplicadas.
Steve Py

mesmo erro ocorrer usando sua solução, eu preciso mudar a minha função também? @Steve Py
elirans

Capturar o SQL gerado e executado no banco de dados. Eu normalmente uso um Profiler para isso, então para o SQL Server e o SSMS, em Ferramentas\SQL Profiler. De execução que contra o seu banco de dados e, em seguida, executar a consulta. Você pode usar um ponto de interrupção na sua aplicação apenas antes de o SaveChanges, em seguida, desmarque a saída do profiler, antes de continuar para limpar anterior ruído e encontrar a sua instrução UPDATE.
Steve Py

Além disso, você pode postar o estruturador da tabela de saída para a sua mesa? A mesa tem um real PK conjunto com as 4 colunas?
Steve Py

Eu adicionei a resposta acima para incluir etapas para verificar a seqüência de caracteres de conexão, bem como verificar em que os dados se existem valores de chave duplicada.
Steve Py

Eu tentei a sua solução. a primeira coisa é olhar como se você perder alguns '=' nos carros var. segunda coisa - quando eu tento fazer a atualização: carros.ActualReturnDate = acctualDate1; eu tenho um erro cs1061.
elirans

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................