18

我对 EF 很陌生,我有一个小问题。

我只想删除数据库中的一个项目。我正在使用 SQL Server 2012 Express、VS2012、AdventureWorks 2012。

我执行的查询如下:

context = new AWEntities();
            var removedItem = context.Addresses
                .Include("StateProvince")
                .Include("SalesOrderHeaders")
                .Include("BusinessEntityAddresses").Single(d => d.AddressID == 11);
            context.Addresses.Remove(removedItem);

context.SaveChanges();

我得到的错误是

DELETE 语句与 REFERENCE 约束“FK_SalesOrderHeader_Address_ShipToAddressID”冲突。冲突发生在数据库“AdventureWorks2012”、表“Sales.SalesOrderHeader”、列“ShipToAddressID”中。该语句已终止。

这实际上是删除其他表中的项目和相应条目的好方法吗?

请指出我正确的方向。

   public partial class Address
    {
        public Address()
        {
            this.BusinessEntityAddresses = new HashSet<BusinessEntityAddress>();
            this.SalesOrderHeaders = new HashSet<SalesOrderHeader>();
        }

        public int AddressID { get; set; }
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string City { get; set; }
        public int StateProvinceID { get; set; }
        public string PostalCode { get; set; }
        public System.Data.Spatial.DbGeography SpatialLocation { get; set; }
        public System.Guid rowguid { get; set; }
        public System.DateTime ModifiedDate { get; set; }

        public virtual StateProvince StateProvince { get; set; }
        public virtual ICollection<BusinessEntityAddress> BusinessEntityAddresses { get; set; }
        public virtual ICollection<SalesOrderHeader> SalesOrderHeaders { get; set; }
    }


public partial class StateProvince
    {
        public StateProvince()
        {
            this.Addresses = new HashSet<Address>();
            this.SalesTaxRates = new HashSet<SalesTaxRate>();
        }

        public int StateProvinceID { get; set; }
        public string StateProvinceCode { get; set; }
        public string CountryRegionCode { get; set; }
        public bool IsOnlyStateProvinceFlag { get; set; }
        public string Name { get; set; }
        public int TerritoryID { get; set; }
        public System.Guid rowguid { get; set; }
        public System.DateTime ModifiedDate { get; set; }

        public virtual ICollection<Address> Addresses { get; set; }
        public virtual CountryRegion CountryRegion { get; set; }
        public virtual ICollection<SalesTaxRate> SalesTaxRates { get; set; }
        public virtual SalesTerritory SalesTerritory { get; set; }
    }
}

public partial class BusinessEntityAddress
{
    public int BusinessEntityID { get; set; }
    public int AddressID { get; set; }
    public int AddressTypeID { get; set; }
    public System.Guid rowguid { get; set; }
    public System.DateTime ModifiedDate { get; set; }

    public virtual Address Address { get; set; }
    public virtual AddressType AddressType { get; set; }
    public virtual BusinessEntity BusinessEntity { get; set; }
}


public partial class SalesOrderHeader
    {
        public SalesOrderHeader()
        {
            this.SalesOrderDetails = new HashSet<SalesOrderDetail>();
            this.SalesOrderHeaderSalesReasons = new HashSet<SalesOrderHeaderSalesReason>();
        }

        public int SalesOrderID { get; set; }
        public byte RevisionNumber { get; set; }
        public System.DateTime OrderDate { get; set; }
        public System.DateTime DueDate { get; set; }
        public Nullable<System.DateTime> ShipDate { get; set; }
        public byte Status { get; set; }
        public bool OnlineOrderFlag { get; set; }
        public string SalesOrderNumber { get; set; }
        public string PurchaseOrderNumber { get; set; }
        public string AccountNumber { get; set; }
        public int CustomerID { get; set; }
        public Nullable<int> SalesPersonID { get; set; }
        public Nullable<int> TerritoryID { get; set; }
        public int BillToAddressID { get; set; }
        public int ShipToAddressID { get; set; }
        public int ShipMethodID { get; set; }
        public Nullable<int> CreditCardID { get; set; }
        public string CreditCardApprovalCode { get; set; }
        public Nullable<int> CurrencyRateID { get; set; }
        public decimal SubTotal { get; set; }
        public decimal TaxAmt { get; set; }
        public decimal Freight { get; set; }
        public decimal TotalDue { get; set; }
        public string Comment { get; set; }
        public System.Guid rowguid { get; set; }
        public System.DateTime ModifiedDate { get; set; }

        public virtual Address Address { get; set; }
        public virtual ShipMethod ShipMethod { get; set; }
        public virtual CreditCard CreditCard { get; set; }
        public virtual CurrencyRate CurrencyRate { get; set; }
        public virtual Customer Customer { get; set; }
        public virtual ICollection<SalesOrderDetail> SalesOrderDetails { get; set; }
        public virtual SalesPerson SalesPerson { get; set; }
        public virtual SalesTerritory SalesTerritory { get; set; }
        public virtual ICollection<SalesOrderHeaderSalesReason> SalesOrderHeaderSalesReasons { get; set; }
    }
4

6 回答 6

21

从您所说的内容中无法真正说明太多,但是您可能会受益于使用 DbModelBuilder 解决级联问题:

            modelBuilder.Entity<Parent>()
                .HasMany<Child>(c => c.Children)
                .WithOptional(x => x.Parent)
                .WillCascadeOnDelete(true);

同样,需要有关您的模型结构的更多信息来确定这是否是正确的方法。

无论是那个还是在您的删除方法中,首先删除所有子项,然后删除父项。

于 2013-08-13T15:01:57.760 回答
12
  modelBuilder.Entity<Parent>()
  .HasMany<Child>(c => c.Children)
  .WithOptional(x => x.Parent)
  .WillCascadeOnDelete(true);

或使用包括

  var adv = db.Adv.Include(b => b.Features)
                  .Include(b => b.AdvDetails)
                  .Include(b => b.AdvGallery)
                  .FirstOrDefault(b => b.Id == id);
  db.Adv.Remove(adv);

对于 .HasMany(...).WithMany(...) 包含就可以了

于 2017-07-05T06:27:26.663 回答
6

您可以在 SQL 端解决此问题

方法一

  • 首先,您需要FK通过 using 查找在哪个表上定义了此约束Replication monitor

  • 右键单击它FK,单击Modify,您应该会出现如下所示的弹出框。

在此处输入图像描述

  • 从弹出框中,Cascade选择del

方法二

ON DELETE CASCADE在约束结束时在 sql 中设置。

于 2018-01-03T10:02:19.550 回答
3

在 EF Core 中,builder 中的语法如下:

builder.HasOne(b => b.Parent )
  .WithMany(a => a.Children)
  .OnDelete(DeleteBehavior.Cascade);

https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete

于 2019-05-23T09:22:12.127 回答
0

当我创建引用实体 A 的实体 B,然后尝试删除实体 A 时出现此错误。SQL/EF 不允许我离开那个悬空的 Id 引用,因为该对象不再存在。级联删除可以解决这个问题,但我希望 B 坚持下去。所以我必须在删除 A 之前从 B 中删除引用:

    var existingContractApprovers = _repo.Query<ChangeOrderApproverForContract>().Where(coafc => coafc.ContractId == key).ToList();
    //remove refs to contract approvers to preserve data integrity
    foreach(var contractApp in existingContractApprovers)
    {
        var associatedChangeOrderApprovers = _repo.Query<ChangeOrderApprover>().AsNoTracking().Where(coafc => coafc.ChangeOrderApproverForContractId == contractApp.Id).ToList();
        foreach(var coApp in associatedChangeOrderApprovers)
    {
            _repo.Edit(coApp);
            coApp.ChangeOrderApproverForContractId = null;
        }
    }
    _repo.SaveChanges();

    //remove the contract approvers
    foreach (var contractApp in existingContractApprovers)
    {
        _repo.Delete(contractApp);
    }
    _repo.SaveChanges();
于 2020-07-06T20:57:09.083 回答
0

您可以在 EF Core 中执行此操作。

modelBuilder.Entity<Parent>()
    .HasMany<Child>(c => c.Children)
    .WithOne(s => s.Parent)
    .OnDelete(DeleteBehavior.Cascade);

更安全的选择是确保在删除父级之前删除所有子级。仅当您完全了解实体之间的关系时,才应在删除时级联。例如,您可能有很多订单与您的电子商务商店中的某个类别相关联。一旦类别被删除,所有订单和任何外键连接到该父类别的实体都将消失。

于 2020-09-04T00:22:17.803 回答