【问题标题】:Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths引入 FOREIGN KEY 约束可能会导致循环或多个级联路径
【发布时间】:2013-10-22 18:58:09
【问题描述】:

我收到了这个错误

引入 FOREIGN KEY 约束 表“Regions”上的“FK_dbo.Regions_dbo.Countries_CountryId”可能会导致 循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。不能 创建约束。查看以前的错误。

我想知道这是否意味着我的数据库设计不好?我读到你关闭了级联或类似的东西,但我不确定这是否能彻底解决问题。

我只是让 EF 通过我的域类生成我的表(此时我没有使用任何数据注释或流畅的映射)。

       public class Country
        {
            public Country()
            {
                this.Stores = new List<Store>();
                this.Regions = new List<Region>();
                Id = GuidCombGenerator.GenerateComb();
            }

            public Guid Id { get; private set; }

            private string name;

            public string Name
            {
                get { return name; }
                set
                {
                    name = value.Trim();
                }
            }

            private string code;

            public string Code
            {
                get { return code; }
                set
                {
                    code = value.Trim();
                }
            }

            public virtual ICollection<Store> Stores { get; set; }
            public virtual ICollection<Region> Regions { get; set; }
        }


          public class City
        {
            public City()
            {
                this.Stores = new List<Store>();
                Id = GuidCombGenerator.GenerateComb();
            }

            public Guid Id { get; private set; }

            private string name;

            public string Name
            {
                get { return name; }
                set
                {
                    name = value.Trim();
                }
            }


            public Guid RegionId { get; set; }
            public virtual Region Region { get; set; }

            public virtual ICollection<Store> Stores { get; set; }
        }


            public class Region
        {
            public Region()
            {
                this.Cities = new List<City>();
              this.Stores = new List<Store>();


                Id = GuidCombGenerator.GenerateComb();
            }

            public Guid Id { get; private set; }


            private string state;

            public string State
            {
                get { return state; }
                set
                {
                    state = value.Trim();
                }
            }


            public Guid CountryId { get; set; }
            public virtual ICollection<City> Cities { get; set; }
            public virtual Country Country { get; set; }
           public virtual ICollection<Store> Stores { get; set; }
        }


  public class Store
    {
        public Store()
        {
            Id = GuidCombGenerator.GenerateComb();

            Users = new List<User>();
        }

        public Guid Id { get; private set; }

        public Guid CountryId { get; set; }
        public Guid CityId { get; set; }
        public Guid RegionId { get; set; }
        public virtual City City { get; set; }
        public virtual Country Country { get; set; }
        public virtual Region Region { get; set; }

        public virtual ICollection<User> Users { get; set; }

    }

会不会是商店的原因?

【问题讨论】:

  • 你能告诉我们所涉及的表,它们的结构是什么,最重要的是:它们之间的 FK 约束是如何设置的?所以你想在地区和国家之间建立一个级联删除,这样如果一个国家被删除,它的所有地区都被删除?听起来很合理 - 问题是:为什么这会导致循环?您还有哪些其他具有级联删除功能的 FK 约束?
  • 好的,我更新了它以显示这些区域,我还没有生成任何表格,因为我先编写代码。
  • 不幸的是,您没有向我们展示 Store 类 .... 我也没有看到任何定义级联删除的代码 ...
  • 我没有定义级联的代码,我只是创建了我的类并希望 EF 生成所有内容。如果我需要一些额外的 tweeking,那么我会制作那些流畅的映射东西。商店已发布。

标签: entity-framework cascading


【解决方案1】:

模型中的所有关系都是必需的,因为所有外键属性(CountryIdRegionIdCityId不可为空。对于所需的一对多关系,EF 将按照惯例启用级联删除。

CountryRegion 有多个Store 表的删除路径,例如,如果您删除Country,则可以通过三个不同的级联路径删除相关的Stores(这是不允许的SQL 服务器):

  • Country -> Store
  • Country -> Region -> Store
  • Country -> Region -> City -> Store

您必须通过使用 Fluent API 禁用级联删除或将某些关系定义为可选(使用可为空的外键 Guid?)来避免此类不明确的删除路径。

或者从除City 之外的所有实体中删除Stores 集合(以及反向引用和FK 属性)。对我来说,这些集合看起来是多余的,因为您可以通过浏览 Regions.Cities.Stores 集合找到 Country 中的所有商店。

【讨论】:

  • 所以 Stores 只会与 City 有关系?
  • @chobo2:是的,我认为这就足够了。
  • +1 信息丰富;啊,对 SQL Server 部分的这种限制很烦人。在很多很多情况下,您有一个在两个表之间实现多对多关系的表,并且您希望在关系表中的这两个表中都有不可为空的外键,并从其中任何一个表中删除这些表级联到关系表。所以我想我们留下了一个非常不理想的解决方案,即让一个外键为空。或者每次都实施自定义触发器。真是个皮塔饼。
  • 错误信息也应该告诉“Store”表,以便我们知道“Store”表存在多次删除冲突。为什么错误消息没有说明?
  • 为什么错误信息没有提到Store表?
【解决方案2】:

DataContext 文件的OnModelCreating 方法中添加modelBuilder.Conventions.Remove&lt;OneToManyCascadeDeleteConvention&gt;(),如下所示:

public class YourDataContext : DbContext
{
    public DbSet<Country> Countries{ get; set; }
    ...


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

    }
}

同样的问题:entity-framework-how-to-solve-foreign-key-constraint-may-cause-cycles-or-multi

【讨论】:

  • 当您对架构设计没有任何控制权时,这是确切的解决方案。
  • so·lu·tion səˈlo͞oSH(ə)n/ 名词 1. 解决问题或处理困难情况的手段。
  • 我不想这样做,但我想尝试一下,但它对我不起作用。我仍然收到 OP 指出的错误。
  • 我可以将此转换仅应用于特定关系吗?
猜你喜欢
  • 2011-05-08
  • 2018-08-08
  • 2017-04-26
  • 2019-10-20
  • 2018-12-14
  • 2013-06-12
相关资源
最近更新 更多