更新 EF Core 中的相关实体

Win*_*rpe 3 entity-framework-core

我使用 Entity Framework Core 并采用代码优先的方法。当将更改保存到对其相关对象之一进行更改的实体时,我遇到了此错误:

“实体类型“Bird”上的属性“BirdId”是键的一部分,因此无法修改或标记为已修改。要使用标识外键更改现有实体的主体,请首先删除依赖项并调用“SaveChanges”,然后将受抚养人与新委托人联系起来。”

当我将更改保存到类型实体Observation并更新到相关Bird对象时,我遇到了错误。我已包含以下模型设置:

public class Observation
{
    [Key]
    public int ObservationId { get; set; }

    // other properties...

    public int BirdId { get; set; }

    public Bird Bird { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Bird 类如下所示:

public class Bird
{
    [Key]
    public int BirdId { get; set; }

    // other properties...

    public ICollection<Observation> Observations { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我仅依赖 EF Core 模型约定(我没有在方法中添加代码OnModelCreating),该约定从 EF 迁移中设置数据库,如下所示:

        migrationBuilder.CreateTable(
            name: "Observation",
            columns: table => new
            {
                ObservationId = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                BirdId = table.Column<int>(nullable: false),
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Observation", x => x.ObservationId);
                table.ForeignKey(
                    name: "FK_Observation_Bird_BirdId",
                    column: x => x.BirdId,
                    principalTable: "Bird",
                    principalColumn: "BirdId",
                    onDelete: ReferentialAction.Cascade);
            });
Run Code Online (Sandbox Code Playgroud)

我是否正确设置了模型?

我用于保存更新的观察的代码如下所示:

            observation.BirdId = model.Bird.BirdId;
            var bird = await _birdRepository.GetBirdAsync(model.Bird.BirdId);
            observation.Bird = bird;

            observation.LastUpdateDate = _systemClock.GetNow;

            await _unitOfWork.CompleteAsync();
Run Code Online (Sandbox Code Playgroud)

然而,我认为问题在于模型中建立关系的方式。任何人都可以阐明这个问题吗?

Gam*_*vil 6

observation.Birdobservation.BirdId按惯例联系在一起。您不应该同时更改两者,通常建议仅更改导航属性。我假设这model是一个视图模型,因此您不能直接使用它的 Bird,但基本上您可以省略第一行代码并简单地设置observation.Bird.

在这种情况下,EF 会感到困惑,因为您试图两次更改关系。

  • 谢谢。我还使用自动映射器将视图模型映射到数据库中的原始观察。这导致 navigation 属性被多次更改! (2认同)