【问题标题】:How to update naviation property with new values in EF Core?如何在 EF Core 中使用新值更新导航属性?
【发布时间】:2019-07-31 13:11:52
【问题描述】:

Soo...我有Product 的这个简单模型:

public class Product {
    public int Id { get; set; }

    // Other things

    public ICollection<ProductAttribute> ProductAttributes { get; set; }
}

还有ProductAttributesProductIdName 作为多字段键。

public class ProductAttribute {
    public int? ProductId { get; set; } // Key
    public ProductAttributeName? Name { get; set; } // Key
    public string Value { get; set; }
}

在我的 WebAPI 项目中,我有这个方法:

public async Task<IActionResult> Patch(Product product) {
    var productExist = await _context.Products.AnyAsync(a => a.Id == product.Id);
    if (!productExist) return NotFound(product.Id);
    _context.Products.Update(product);
    await _context.SaveChangesAsync();
    return Ok();
}

我假设如果有人在 productAttributes 中发送我的 JSON 和不同的数据,我应该将值切换到完全覆盖的新值 或删除旧值。就像在这个例子中

OldProduct
* Name
* ProductAttributes:
    * Value 1
    * Value 2
NewProduct
* Name
* ProductAttributes:
    * Value 2
    * Value 3

所以Value1 应该被删除,Value3 应该被添加。但相反,我在SaveChangesAsync() 上遇到了一个例外:

System.ArgumentException: 'An item with the same key has already been added. Key: System.Object[]'

我猜可能是因为它正在尝试添加Value2,但它已经存在。

我应该如何正确更新导航属性?

@更新

感谢@cjens19,我只是更改了更新方法并使用了 Automapper:

public async Task<IActionResult> Patch(Product product) {
    var productFromDb = await _context.Products.Include(p => p.ProductAttributes).SingleOrDefaultAsync(product1 => product1.Id == product.Id);
    if (productFromDb == null) return NotFound(product.Id);
    Mapper.Map(product, productFromDb);
    await _context.SaveChangesAsync();
    return Ok();
}

【问题讨论】:

    标签: c# asp.net-core .net-core entity-framework-core


    【解决方案1】:

    你在 // ... 检查模型是否存在代码中做了什么?

    您应该使用以下内容从上下文中检索现有的 Product 实体:

    var entity = _context.Products.SingleOrDefault(p => p.Id == product.Id);
    

    然后,如果实体不为空,您可以使用 Product 参数传入的值设置他的属性。

    最后,您将调用更新和保存。这不应该给你任何 ef 核心错误。

    【讨论】:

    • 啊,抱歉编辑。所以你仍然没有从上下文中检索实体。与其做一个返回布尔值的 AnyAsync,不如做一个 SingleOrDefault (就像我原来的评论一样)。您仍然可以对其进行空值检查,因为 OrDefault 将返回未找到实体的空值。然后您可以更新从该检索返回的实体。
    • 所以...而不是使用_context.Products.Update(product),我应该以某种方式映射或手动分配新值到从SingleOr检索到的跟踪实体?
    • 是的。在您映射新值并执行 SaveChanges 后,跟踪将为您处理更新。
    猜你喜欢
    • 2021-11-10
    • 2018-04-03
    • 1970-01-01
    • 2021-01-16
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 1970-01-01
    相关资源
    最近更新 更多