C# 同一类型的一对一关系实体

C# 同一类型的一对一关系实体,c#,asp.net-core,ef-core-2.2,C#,Asp.net Core,Ef Core 2.2,我是ASP.NetCore和EF Core的新手 我很难想出如何处理这种情况: 我有一个可用研究的列表,每个研究都有一个可用研究的列表。但是,一个阶段也可能取决于前一阶段(但不是强制性的),同样的情况也发生在研究中,一项研究可能取决于前一项研究。以下是模型类: 业务对象: public class BusinessObject : IBusinessObject { #region Constructors public BusinessObject()

我是ASP.NetCore和EF Core的新手

我很难想出如何处理这种情况:

我有一个可用研究的列表,每个研究都有一个可用研究的列表。但是,一个阶段也可能取决于前一阶段(但不是强制性的),同样的情况也发生在研究中,一项研究可能取决于前一项研究。以下是模型类:

业务对象:

 public class BusinessObject : IBusinessObject
    {
        #region Constructors
        public BusinessObject()
        {
            Id = Guid.NewGuid().ToString();
        }

        public BusinessObject(string name) :  this()
        {
            Name = name;
        }
        #endregion

        #region IBusinessObject implementation
        public string Id { get; set; }
        public string Name { get; set; }

        #endregion
    }
   public class AvailableStudy : BusinessObject
    {
        #region Constructors
        public AvailableStudy() : base()
        {
            Stages = new List<AvailableStage>();
        }

        public AvailableStudy(string name) : base(name)
        {
            Stages = new List<AvailableStage>();
        }
        #endregion


        [ForeignKey("DependsOn")]
        public string DependsOnId { get; set; }

        #region Lazy-Load Properties
        public virtual List<AvailableStage> Stages { get; set; }

        public virtual AvailableStudy DependsOn { get; set; }
        #endregion
    }
public class AvailableStage : BusinessObject
    {
        #region Constructors
        public AvailableStage() : base()
        {
        }

        public AvailableStage(string name) : base(name)
        {
        }

        public AvailableStage(string name, AvailableStudy study) : base(name)
        {
            Study = study;
        }
        #endregion


        #region Properties
        [Required]
        public string StudyId { get; set; }

        public double Percentage { get; set; }

        public int Duration { get; set; }

        [ForeignKey("DependsOn")]
        public string DependsOnId { get; set; }
        #endregion

        #region Lazy-Load Properties
        public virtual AvailableStage DependsOn { get; set; }

        [ForeignKey("StudyId")]
        public virtual AvailableStudy Study { get; set; }
        #endregion        
    }
可用性研究:

 public class BusinessObject : IBusinessObject
    {
        #region Constructors
        public BusinessObject()
        {
            Id = Guid.NewGuid().ToString();
        }

        public BusinessObject(string name) :  this()
        {
            Name = name;
        }
        #endregion

        #region IBusinessObject implementation
        public string Id { get; set; }
        public string Name { get; set; }

        #endregion
    }
   public class AvailableStudy : BusinessObject
    {
        #region Constructors
        public AvailableStudy() : base()
        {
            Stages = new List<AvailableStage>();
        }

        public AvailableStudy(string name) : base(name)
        {
            Stages = new List<AvailableStage>();
        }
        #endregion


        [ForeignKey("DependsOn")]
        public string DependsOnId { get; set; }

        #region Lazy-Load Properties
        public virtual List<AvailableStage> Stages { get; set; }

        public virtual AvailableStudy DependsOn { get; set; }
        #endregion
    }
public class AvailableStage : BusinessObject
    {
        #region Constructors
        public AvailableStage() : base()
        {
        }

        public AvailableStage(string name) : base(name)
        {
        }

        public AvailableStage(string name, AvailableStudy study) : base(name)
        {
            Study = study;
        }
        #endregion


        #region Properties
        [Required]
        public string StudyId { get; set; }

        public double Percentage { get; set; }

        public int Duration { get; set; }

        [ForeignKey("DependsOn")]
        public string DependsOnId { get; set; }
        #endregion

        #region Lazy-Load Properties
        public virtual AvailableStage DependsOn { get; set; }

        [ForeignKey("StudyId")]
        public virtual AvailableStudy Study { get; set; }
        #endregion        
    }
最后,我的上下文类的onmodel创建:

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<AvailableStudy>().ToTable("AvailableStudies");
            modelBuilder.Entity<AvailableStudy>().HasMany(i => i.Stages).WithOne(c => c.Study);
           modelBuilder.Entity<AvailableStudy>().HasOne(i => i.DependsOn);

            modelBuilder.Entity<AvailableStage>().ToTable("AvailableStages");
            modelBuilder.Entity<AvailableStage>().HasOne(i => i.Study).WithMany(u => u.Stages);
            modelBuilder.Entity<AvailableStage>().HasOne(i => i.DependsOn);         
        }
然后,我将这些研究添加到DBContext类中的适当DBSet中,当我尝试保存更改时,抛出一个异常,该异常表示:

SqlException:INSERT语句与外键同一表约束“FK\u AvailableStates\u AvailableStates\u DependsOnId”冲突。冲突发生在数据库“Latendesamples”、表“dbo.AvailableStates”、列“Id”中。 声明已终止

我真的不明白发生了什么事

谢谢你的帮助

完整的异常结果是:

Microsoft.EntityFrameworkCore.DbUpdateException
  HResult=0x80131500
  Message=An error occurred while updating the entries. See the inner exception for details.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(DbContext _, ValueTuple`2 parameters)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IReadOnlyList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at LabManager.DataModel.Data.DbSeeder.CreateStudiesWithStages(ApplicationDbContext dbContext) in W:\LabManager\DataModel\src\Data\DbSeeder.cs:line 113
   at LabManager.DataModel.Data.DbSeeder.Seed(ApplicationDbContext dbContext, RoleManager`1 roleManager, UserManager`1 userManager, IHostingEnvironment env) in W:\LabManager\DataModel\src\Data\DbSeeder.cs:line 22
   at LabManagerWebPage.Extensions.ServiceExtensions.ConfigureDBContext(IApplicationBuilder app, IHostingEnvironment env) in W:\LabManager\LabManagerWebPage\Extensions\ServiceExtensions.cs:line 156
   at LabManagerWebPage.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env) in W:\LabManager\LabManagerWebPage\Startup.cs:line 107

Inner Exception 1:
SqlException: The INSERT statement conflicted with the FOREIGN KEY SAME TABLE constraint "FK_AvailableStages_AvailableStages_DependsOnId". The conflict occurred in database "LateAndesSamples", table "dbo.AvailableStages", column 'Id'.
The statement has been terminated.

你的问题是基类。它必须是抽象的。否则,它将创建关系继承,EF Core支持的唯一策略是每个层次的表,也称为单表继承。这意味着对于像
BusinessObject
这样的看似全局的基类,您最终将得到一个巨大的表,其中包含所有其他类型。换句话说,就是一团糟

通过将其抽象化,派生类型将继承该行为,但它们仍将各自获得自己的表。

我解决了

解析JSON文件后,我调用了以下方法:

//availables is a list of availiables studies generated after parsing json file

dbContext.AvailableStudies.AddRange(availables);
dbContext.SaveChanges();

但当我详细查看时,没有依赖项的阶段包含DependsOnId属性上的空字符串,而不是null。将空字符串替换为null后,它可以正常工作

谢谢你,安瑟!很抱歉出现了noob问题,但当调用“modelBuilder.Entity().ToTable(“AvailableStudies”);”等时,OnModelCreating方法无法解决此问题。无论如何,我已经听从了您的建议。再次感谢你!