实体框架核心-修改的拥有型密钥

时间:2019-09-20 08:08:04

标签: c# azure-webjobs ef-core-2.2

将更改保存在数据库中时,将返回以下消息的异常:

  

实体类型'Order.CustomerDeliveryDetails#CustomerDetails'的属性'OrderId'是键的一部分,因此无法进行修改或将其标记为已修改。要使用标识的外键更改现有实体的委托人,请先删除依赖项,然后调用“ SaveChanges”,然后将依赖项与新委托人相关联。

使用“代码优先”方法以实体框架核心实现数据库。 Order.CustomerDeliveryDetails是实体CustomerDetails的拥有类型(Order类型)。 CustomerDetails没有名为OrderId的属性。据我了解,OrderIdimplicit key,由实体框架核心生成为shadow property

这些类的结构如下:

public class Order
{
    public int Id { get; set; }
    public CustomerDetails CustomerDeliveryDetails { get; set; }
}

[Owned]
public class CustomerDetails
{
    public string Street { get; set; }
}

对象更新如下:

var order = await orderContext.Orders
        .Where(o => o.Id== updateOrder.Id)
        .FirstOrDefaultAsync();

order.CustomerDeliveryDetails.Street = updateOrder.CustomerDeliveryDetails.Street;
await orderContext.SaveChangesAsync();

我无法理解的是在无法直接在代码中直接访问OrderId的情况下。

我唯一想到的可能是导致此错误的原因是,此更新是在Azure的定时Web作业上运行的。更新通过相关单元测试的事实支持了这种预感。可能与race condition有关吗?​​

更新

我相当确定该错误来自某种竞争状况。定时的webjob加载需要每2分钟更新一次的订单列表。只要列表包含的订单少于+ -100,更新就可以正常进行,但是一旦列表变得更长,更新就会开始失败。

如果列表过长,webjob可能无法在2分钟内完成所有订单的更新。

通过依赖项注入来添加上下文,如下所示:

serviceProvider.AddDbContext<OrdersContext>(options => options.UseSqlServer(ctx.Configuration["ConnectionString"], sqlOptions => sqlOptions.EnableRetryOnFailure()));

我最好的想法是,上下文在Webjob的多个调用之间共享,这会导致错误。

1 个答案:

答案 0 :(得分:0)

这归结为您与数据库的关系。您使用数据库优先还是代码优先的方法?如何定义模型? Order,CustomerDetails和CustomerDeliveryDetails表之间的关系是什么? 请提供代码,我们将为您提供解决方案。