错误:对 Cosmos DB 和 Entity Framework Core 3.1.2 进行“更新”调用时出现“备用键属性 'id' 为 null”

Jas*_*SFT 6 c# entity-framework entity-framework-core asp.net-core

假设我有一个PersonModel如下的简单模型,我FirstName从 ASP.NET Core 3.1 Blazor 或 MVC UI(Web 表单)更新属性:

public class PersonModel 
{
  public Guid PersonModelId { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我将模型发送到 http 触发的 Azure 函数并绑定到模型。这是我实现 EF Core 并执行以下操作来更新它的地方:

public class PersonModel 
{
  public Guid PersonModelId { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我使用此模型创建或删除实体没有任何问题,并且根据以下文章,我没有看到创建一个根据任何特定存储库要求(即分区键或主键等)“干净”的模型有任何问题但是我似乎无法运行更新代码而不出现以下错误:

无法跟踪“PersonModel”类型的实体,因为备用键属性“id”为 null。

有谁知道模型的具体要求并使用此方法来更新实体?有没有像文档文章中的示例一样简单/优雅的替代方案?

我已经尝试过,_dbContext.Update(entity)但得到了完全相同的错误,这使我相信我的模型需要“ID”属性。

我还尝试DbContext按如下方式修改我的设置:

public async Task<int> UpdateAsync(TEntity entity)
{
  _dbSet.Attach(entity); //<--this throws the error
  _dbContext.Entry(entity).State = EntityState.Modified;
  return await _dbContext.SaveChangesAsync();
}
Run Code Online (Sandbox Code Playgroud)

...但这只会给我带来同样的错误,并且也不会改变实体的存储方式。

更新

按照下面接受的答案的指导,我编写了以下更改以使这项工作正常进行:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<PersonModel>().HasAlternateKey(p => p.PersonModelId);
}
Run Code Online (Sandbox Code Playgroud)

jde*_*rth 4

编辑:我认为问题是由 EF Core 自动为每个名为“id”的项目生成的属性引起的,特别是全部小写并与模型中定义的密钥分开。似乎特定于 Cosmos DB 提供程序,并且 EF Core -> 数据库提供程序 -> Cosmos 的文档中的“使用断开连接的实体”部分下注明了空值问题。

显然,EF Core 仅在实体进入“已添加”状态时生成此属性。因此,当您调用 Attach 时,此“id”属性为 null,因此出现异常。文档中列出了一种解决方法,其中的解释比我能给出的要好得多。

下面链接到 Cosmos 提供商的 EF Core 文档页面。滚动到概述页面底部,找到涵盖此内容的断开实体部分。

https://learn.microsoft.com/en-us/ef/core/providers/cosmos/?tabs=dotnet-core-cli#working-with-disconnected-entities