为什么将导航属性设置为 null 将外键属性也设置为 null?

问题描述 投票:0回答:3

我使用 EF Core 7.0.3。

这是我的实体:

[Table("Common_T230")]
public class Employment 
{
    [Column("F230_ID")]
    public int Id { get; set; }

    [Column("F230_14")]
    public string VehicleNumber { get; set; }
    public virtual Vehicle Vehicle { get; set; }
}

以下是关系的定义:

modelBuilder.Entity<Employment>()
            .HasOne(e => e.Vehicle)
            .WithMany()
            .HasPrincipalKey(e => e.VehicleNumber)
            .HasForeignKey(e => e.VehicleNumber);

现在,当我加载就业并设置

VehicleNumber
(外键值)并将导航属性设置为 null 时,
ctx.SaveChanges()
会将 null 更改为
F230_14
(
VehicleNumber
)。

有人可以向我解释为什么会发生这种情况吗?

VehicleNumber
包含有效的外键值。

var employment = query.Include(x => x.Vehicle)
                      .FirstOrDefault(x => x.Date == currentDate 
                                           && x.ProjectNumber == projectNumber);
employment.PersonelNumber = personelNumber;
employment.Vehicle = null;
employment.VehicleNumber = vehicleNumber ?? "";

// here, EF Core will save null to F230_14 (VehicleNumber)
ctx.SaveChanges();
c# entity-framework-core navigation-properties ef-core-7.0
3个回答
0
投票

当您将导航属性设置为 NULL 时,您是在说“该对象没有关联的车辆”,因此没有外键值。可能存在这样的情况(例如延迟加载):您从外键值开始但没有对象(我有一段时间没有使用 EF),但如果您显式地将对象设置为 NULL,我希望它设置 FK 值也为 NULL。


0
投票

这与底层数据存储表示相关数据的方式有关。如果您查看代表您的实体的数据库表,它上面没有

Vehicle
。车辆数据行与就业行关联的概念是通过具有与
VehicleNumber
行的主键匹配的
F230_14
属性(
Vehicle
字段)来建模的。

因此,从数据库中的

Employment
中删除车辆的唯一方法是将
VehicleNumber
设置为空。当您将
Vehicle
属性设置为 null 时,实体框架假定这是您的意图,因此当您保存更改时,它会更改该值。


0
投票

在 EF 中,如果您同时拥有 FK 属性和导航属性,则对导航属性的更改优先,即使您设置了 both 值也是如此。所以答案是,如果您想通过 FK 更新导航属性,只需设置 FK 并且不要触摸导航属性。 SaveChanges 后,EF 将自动加载并关联新的导航属性。 (如果它首先是急切加载的)

var employment = query
    .Include(x => x.Vehicle)
    .FirstOrDefault(x => x.Date == currentDate && x.ProjectNumber == projectNumber);
employment.PersonelNumber = personelNumber;
employment.VehicleNumber = vehicleNumber;

虽然我怀疑您可能不想将 VehicleNumber 设置为空字符串(如果它为 null),而是如果没有关联的 Vehicle 将其设置为 #null。 VehicleNumber 是一个 FK,因此除非您的数据库中有一条 ID 为 string.Empty 的车辆记录(例如“未分配”),否则如果您碰巧遇到 #null 场景,#null 防护可能会给您带来问题。

© www.soinside.com 2019 - 2024. All rights reserved.