entity.Items.Clear()在EF中做了什么?

时间:2017-04-02 16:20:59

标签: entity-framework entity-framework-6

在我正在处理的项目中,每当我清除项目列表后调用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与VehicleCompanyPhone

的处理方式不同

1 个答案:

答案 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();

会工作

  1. 包含
  2. 之前的查询
  3. 包括您要删除的所有实体;
  4. 从父(公司对象)中逐一删除/删除/删除