附加类型为“”的实体失败,因为另一个实体具有相同的主键值

Attaching an entity of type '' failed because another entity has the same primary key value

我的 WebApi 应用程序有一个小问题。 当我将新实体添加到我的数据库时会出现此问题。

实体:

public sealed class Lot : Entity
{
    [Required, DefaultValue(false)]
    public bool IsActive { get; set; }

    [Required, DefaultValue(false)]
    public bool IsDelete { get; set; }

    [Required, DefaultValue(false)]
    public bool InCredit { get; set; }

    [DefaultValue(1), Range(1, 10)]
    public int PhaseNumber { get; set; }

    [Required]
    public decimal DesiredPrice { get; set; }

    public Guid? AcceptedBetId { get; set; }

    [Required]
    public DateTime CreationDate { get; set; }

    public DateTime ExpirationDateTime { get; set; }

    [Required]
    public string City { get; set; }

    public User User { get; set; }

    public Car Car { get; set; }

    public ICollection<Bet> Bets { get; set; }

    public Lot()
    {
        Bets = new List<Bet>();
    }
}

public sealed class Bet : Entity
{
    [Required, Range(0.0, double.MaxValue)]
    public decimal Price { get; set; }

    [Required]
    public DateTime CreationDate { get; set; }

    [Range(0, int.MaxValue)]
    public int BetNumber { get; set; }

    public Lot Lot { get; set; }

    public User User { get; set; }
}

我想在我的数据库中添加新 Bet 实体的代码:

Lot lot;
using (LotsManager lotsManager = new LotsManager())
{
     lot = await lotsManager.GetLotAsync(model.LotId);
}

User user;
using (UserManager userManager = new UserManager())
{
      user = await userManager.GetUserAsync(model.UserInfoId);
}

var bet = new Bet
{
      Id = Guid.NewGuid(),
      Price = model.Price,
      CreationDate = DateTime.Now,
      BetNumber = lastBetNumber + 1,
      Lot = lot,
      User = user
 };

 await _betsManager.SaveBetAsync(bet);

在这个地方将我的实体添加到数据库中(数据库:我的SQL)

protected async Task Save<T>(T entity) where T : Entity
    {
        using (var dbContextTransaction = _context.Database.BeginTransaction())
        {
            try
            {
                var dbEntity = await _context.Set<T>().SingleOrDefaultAsync(x => x.Id == entity.Id);

                _context.Set<T>().Attach(entity);
                _context.Entry(entity).State = dbEntity != null ? EntityState.Modified : EntityState.Added;

                await _context.SaveChangesAsync();
                dbContextTransaction?.Commit();
            }
            catch (DbEntityValidationException ex)
            {
                dbContextTransaction?.Rollback();

                var error = ex.EntityValidationErrors.First().ValidationErrors.First();
                throw new InvalidModelException(error.ErrorMessage);
            }
            catch (Exception ex)
            {
                dbContextTransaction?.Rollback();

                throw new InvalidDbOperationException(ex.Message);
            }
        }
    }

当我调用我的保存方法时,我的代码抛出这个异常:

Attaching an entity of type 'WebCar.Domain.Entities.Lot' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

我正在尝试使用

_context.Set<T>().Attach(entity);
_context.Entry(entity).State = EntityState.Unchanged;
or
_context.Entry(entity).State = EntityState.Unchanged;

但是代码仍然报错。

这是导致问题的代码:

  var dbEntity = await _context.Set<T>().SingleOrDefaultAsync(x => x.Id == entity.Id);
  _context.Set<T>().Attach(entity);

在这种情况下,如果您找到一个现有实体,它只是存储在上下文中。如果您尝试添加一个已经存在的,EF 无法处理。有几种方法可以解决这个问题。我会展示两个:

 var dbEntity = await _context.Set<T>().AsNoTracking().SingleOrDefaultAsync(x => x.Id == entity.Id);

理论上,如果你不追踪,那你应该可以添加另一个。

不过,我觉得这样更好:

bool doesEntityExist = await _context.Set<T>().Any(x => x.Id == entity.Id);
_context.Set<T>().Attach(entity);
_context.Entry(entity).State = doesEntityExist ? EntityState.Modified : EntityState.Added;