相同类型的一对一关系实体

时间:2019-07-03 14:07:04

标签: c# asp.net-core ef-core-2.2

我是ASP.NetCore和EF Core的新手。

我很难弄清楚如何处理这种情况:

我有一个 AvailableStudy 列表,每个研究都有一个 AvailableStage 列表。而且,一个阶段可以取决于先前的阶段(但不是强制性的),并且研究也是如此,一项研究可以取决于先前的研究。这是模型类:

BusinessObject:

 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        
    }

最后,我的上下文类的OnModelCreating:

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);         
        }

我正在解析JSON文件,以生成研究的列表,包括其阶段和依赖性。

JSON文件的一部分

{
  "Studies": [
    {
      "Name": "Concentrated",
      "DependsOn": "",
      "Stages": [
        {
          "Name": "IsConcentratedDone",
          "Percentage": 25,
          "Duration": 1
        },
        {
          "Name": "WasDescribed",
          "Percentage": 25,
          "Duration": 1
        },
        {
          "Name": "HasPhotos",
          "Percentage": 25,
          "Duration": 1
        },
        {
          "Name": "ReportFinished",
          "Percentage": 25,
          "Duration": 1
        }
      ]
    },
    {
      "Name": "AFT",
      "DependsOn": "Concentrated",
      "Stages": [
        {
          "Name": "IsMountDone",
          "Percentage": 25,
          "Duration": 1
        },
        {
          "Name": "SendedToIrradiation",
          "Percentage": 25,
          "Duration": 1
        },
        {
          "Name": "WasRecepted",
          "Percentage": 25,
          "Duration": 1
        },
        {
          "Name": "WasMeasured",
          "Percentage": 25,
          "Duration": 1
        }
      ]
    }
  ]
}

然后,我将这些研究添加到DBContext类中的适当DBSet中,并且当我尝试保存更改时会抛出一个异常:

SqlException:INSERT语句与FOREIGN KEY SAME TABLE约束“ FK_AvailableStages_AvailableStages_DependsOnId”发生冲突。数据库“ LateAndesSamples”的表“ dbo.AvailableStages”的列“ 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.

2 个答案:

答案 0 :(得分:1)

您的问题是基类。它需要是抽象的。否则,它将创建关系继承,并且EF Core支持的唯一策略是逐层表,AKA单表继承。这意味着对于像post_save这样的看似全局基类,您将最终得到一个巨大的表,并将所有其他类型塞入其中。换句话说,一团糟。

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

答案 1 :(得分:0)

我解决了!

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

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

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

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