在我正在处理的项目中,每当我清除项目列表后调用SaveChanges()
,我都会收到此错误:
操作失败:无法更改关系,因为 一个或多个外键属性是不可为空的。当一个 改变了关系,相关的外键属性是 设置为空值。如果外键不支持空值, 必须定义新的关系,外键属性必须是 分配了另一个非空值,或者不相关的对象必须是 删除。
我有这两个有一对多关系的类(最简单的实现):
public class Company
{
public int Id {get; set;}
public string Name {get; set;}
public virtual List<Vehicle> Vehicles {get; set;}
}
public class Vehicle
{
public int Id {get; set;}
public string Model {get; set;}
}
我猜测调用company.Vehicles.Clear()
应该更新Vehicle表中自动生成的列Company_Id
,将其值设置为null,但这似乎不是上述错误指示的情况。
所以我想知道company.Vehicles.Clear()
究竟在数据库方面做了什么?
修改
感谢@McKabue的回答和他提供的链接,我发现这是解决方案,这是完整的代码:
var company = context.Set<GENCompany>().
Include(m => m.Vehicles).
Include(m => m.Quotes).
Include(m => m.Phones).
Include(m => m.Persons).
Include(m => m.Leads).
Include(m => m.Emails).
Include(m => m.Drivers).
Include(m => m.Deals).
Include(m => m.Comments).
Include(m => m.Branches).
Include(m => m.Addresses).
SingleOrDefault(m => m.Id == companyModel.Id);
context.Entry(company).State = EntityState.Modified;
company.Vehicles.Clear();
company.Drivers.Clear();
company.Quotes.Clear();
company.Persons.Clear();
company.Leads.Clear();
company.Deals.Clear();
company.Branches.Clear();
var phones = context.CompanyPhones.Where(x => x.CompanyId == companyModel.Id);
context.CompanyPhones.RemoveRange(phones);
var emails = context.CompanyEmails.Where(x => x.CompanyId == companyModel.Id);
context.CompanyEmails.RemoveRange(emails);
var comments = context.CompanyComments.Where(x => x.CompanyId == companyModel.Id);
context.CompanyComments.RemoveRange(comments);
var addresses = context.CompanyAddresses.Where(x => x.CompanyId == companyModel.Id);
context.CompanyAddresses.RemoveRange(addresses);
对于某些实体,使用.Clear()语法删除它们,通过获取其记录并删除所有实体(不仅仅是关系)来删除其他实体。它在当前的设计中非常有意义,例如在公司的创建页面中,手动添加手机数据,而从下拉菜单中选择车辆,虽然它使这完美感觉我觉得很困惑,以确定为什么会发生这种情况例如,这里是CompanyPhone类:
public class GENCompanyPhone
{
[Key]
public long PhoneId { get; set; }
public long CompanyId { get; set; }
public long PhoneTypeId { get; set; }
public DateTime DateCreated { get; set; } = DateTime.Now;
public DateTime DateUpdated { get; set; } = DateTime.Now;
public Guid? CreatedById { get; set; }
public bool IsPublish { get; set; } = false;
public bool IsActive { get; set; } = false;
[MaxLength(255)]
[Index(IsUnique = true)]
public string PhoneNumber { get; set; }
[ForeignKey("CompanyId")]
public virtual GENCompany Company { get; set; }
}
另一方面,这是车辆类:
public class GENVehicle
{
public long Id { get; set; }
public long? BrandId { get; set; }
[ForeignKey("BrandId")]
public GENBrand Brand { get; set; }
public string Model { get; set; }
public DateTime? LicenseIssueDate { get; set; }
public Guid? CreatedById { get; set; }
[ForeignKey("VehicleTypeId")]
public virtual GENVehicleType VehicleType { get; set; }
public long? VehicleTypeId { get; set; }
public long? LicenseIssuerId { get; set; }
[ForeignKey("LicenseIssuerId")]
public GENEmployee LicenseIssuer { get; set; }
}
我无法准确确定为什么EF与Vehicle
和CompanyPhone
答案 0 :(得分:1)
这意味着您正在清除另一个表中引用的记录。所以,EF警告你......有些方法可以通过设置Cascade delete
来避免这种情况修改强> 要从父表中删除子元素,需要加载子实体。
修改2
var company = context.Set<GENCompany>().Where(m => m.Id == companyModel.Id);
Include(m => m.Vehicles).
Include(m => m.Quotes).
Include(m => m.Phones).
Include(m => m.Persons).
Include(m => m.Leads).
Include(m => m.Emails).
Include(m => m.Drivers).
Include(m => m.Deals).
Include(m => m.Comments).
Include(m => m.Branches).
Include(m => m.Addresses).SingleOrDefault();
company.Vehicles.Clear();
company.Drivers.Clear();
company.Quotes.Clear();
company.Persons.Clear();
company.Leads.Clear();
company.Deals.Clear();
company.Branches.Clear();
会工作