我使用 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();
当您将导航属性设置为 NULL 时,您是在说“该对象没有关联的车辆”,因此没有外键值。可能存在这样的情况(例如延迟加载):您从外键值开始但没有对象(我有一段时间没有使用 EF),但如果您显式地将对象设置为 NULL,我希望它设置 FK 值也为 NULL。
这与底层数据存储表示相关数据的方式有关。如果您查看代表您的实体的数据库表,它上面没有
Vehicle
。车辆数据行与就业行关联的概念是通过具有与 VehicleNumber
行的主键匹配的 F230_14
属性(Vehicle
字段)来建模的。
因此,从数据库中的
Employment
中删除车辆的唯一方法是将VehicleNumber
设置为空。当您将 Vehicle
属性设置为 null 时,实体框架假定这是您的意图,因此当您保存更改时,它会更改该值。
在 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 防护可能会给您带来问题。