实体框架核心在调用SaveChanges()时尝试插入重复的记录

时间:2016-12-17 13:55:13

标签: c# entity-framework entity-framework-core

我的实体是:

public class Customer
{
   ...
   public virtual ICollection<ShoppingCartItem> ShoppingCartItems { get; set; }
   ...
}

public class ShoppingCartItem
{
   public string CustomerId { get; set; }
   public int ProductId { get; set; }
   public virtual Customer { get; set; }
   public virtual Product{ get; set; }
   ...
}

add方法是:

public async Task AddAsync(TEntity entity)
{
    await Task.Factory.StartNew(() => this.entities.Add(entity));
}

我要添加的实体是:

ShoppingCartItem()
{
    CustomerId = "xxxxx",
    ProductId = 1,
    Customer = null,
    Product = null 
}

当我调用SaveChanges()时,EF正在尝试为ShoppingCartItem插入两个相同的记录。 ShoppingCartItem已创建并仅添加到上下文一次。任何想法可能是错的?

编辑:

这就是我调用AddSync方法的方法:

public async Task AddNewCartItem(ShoppingCartItem shopingCartItem)
    {
        await this.ShoppingCartItemRepository.AddAsync(shopingCartItem);
        await this.SmartStoreWorkData.CompleteAsync();
    }

2 个答案:

答案 0 :(得分:3)

DbContext not thread safe 。毫无意义地,正如评论中所述 - 在很可能是不同的主题中执行您的.Add()时,您会混淆DbContextAdd()纯粹是一种记忆中的操作;没有理由试图让它异步。改变这一点,我认为它将解决问题。

public void Add(TEntity entity)
{
    this.entities.Add(entity);
}

如果您的问题中未显示任何其他类似用法,请将其更改为同步。

可以做&#34;正确&#34;与DbContext异步,但它仅适用于实际与数据库通信的方法,而不是内存中的方法,并且通常不涉及Task.<anything>,只提供async方法。< / p>

修改:为了完整性,上面的链接适用于EF6,但在EF Core中,DbContext也是not thread-safe

答案 1 :(得分:1)

更新:我做了以下事情:

  • 克隆您的回购链接:SmartStoreNETCore
  • 使用新的EF工具(preview4)
  • 迁移到.NET Core 1.1
  • 添加了 EF ModelBuilder
  • 中指定的配置
  • 已应用迁移和更新的数据库

命令:

I2
  • dotnet ef --startup-project ../SmartStoreNetCore.Web/ migrations add ChangeShoppingCartItemKey dotnet ef --startup-project ../SmartStoreNetCore.Web/ database update

    中删除了以下重复标记

    _Layout.cshtml

  

<script src="~/js/site.js" asp-append-version="true"></script>包含添加到购物车功能的点击事件处理程序

  • 启动网站,一切按预期工作,没有重复的购物车商品,数量按预期更新

enter image description here

总结

  

我可以完全确认以下方法被调用两次,然后删除对site.js的重复引用:

site.js

对我来说,为什么在通过调试

之前没有意识到这一点,这是一种谜

EF ModelBuilder

您的配置应如下所示:

 public async Task AddNewCartItem(ShoppingCartItem shopingCartItem)
 {
     await this.ShoppingCartItemRepository.AddAsync(shopingCartItem);
     await this.SmartStoreWorkData.CompleteAsync();
 }

自动生成值不会将其定义为主键