我是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.
答案 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后,它可以正常工作!