我被問題困住了,我試圖以正確的方式解決問題。
我有多個一對多的“擁有”關系。但是我在兩個孩子之間有重復的關系 Story 應該有一個 List of Variable s 并且鏈接的孩子Change應該指向這個 List 中的一個變數。我無法將一個類設定為由 2 個物體擁有,并且僅通過“擁有”關系我無法一次保存整個結構。我的代碼結構的示例。
編輯:另一個問題來自TransitionOption,它具有它所屬的 Step 和它指向的下一個Step 。
public class Story //Main structure example class - A before Edit
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
...name, creator...
[ForeignKey("FK_Story_ID")]
public List<Step> Steps { get; set; } //Set as OwnsMany
[ForeignKey("FK_Story_ID")]
public List<Variable> Variables { get; set; } //Set as OwnsMany , Full list of Variables, that will be shown, which can but does not need to be changed during Step transitions
}
//example class with some main text about changes like part of the story
public class Step
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
...some text...
[ForeignKey("FK_Step_ID")]
public List<TransitionOption> TransitionOptions { get; set; } //Set as OwnsMany
public int FK_Story_ID { get; set; }
}
//example class for some option pointing to another Step
public class TransitionOption
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("FK_TransitionOption_ID")]
public List<Change> Changes { get; set; } //Set as OwnsMany
public int FK_Step_ID { get; set; }
public int FK_NextStep_ID { get; set; } //this will also cause problem and I forgot to mention it before Edit
}
//referencing to one Variable from List Variables in Story
public class Change
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("FK_Change_ID")]
public Variable ChangingVariable { get; set; } //Set as OwnsOne/HasOne - or another way around with List of Changes in Variable. But this is more suitable for my case
public int FK_TransitionOption_ID { get; set; }
}
//Child that I need to have in both one Story (Story OwnsMany Variables) and multiple Changes (Change has/owns one Variable respectively Variable has/owns multiple Changes)
public class Variable
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
...Starting value, conditions, type (text/number)...
public int FK_Change_ID { get; set; }
}
狀態將在最終程序中保存,因此我不需要在資料庫中跟蹤它們。這更像是所有轉換和變數的模板和持有者。這個例子展示了一個類似于互動故事的東西。這有點符合我的人際關系。
問題是,我不知道如何最好地為 EF Core 指定這種關系。編輯:另一個問題是TransitionOption具有它所屬的 Step 和它指向的下一個Step 。這個問題我在編輯為更易讀的示例格式時發現了。
我正在嘗試擁有關系 Story-Variable 并擁有擁有關系 Change-Variable 或 Variable-Change ,這會在遷移時引發錯誤。有了Story-Variable 關系,保存會引發外鍵違規,因為 FK 為 0,因為 Story 尚未保存且沒有 ID,而此時 0 以某種方式被視為有效 ID。我想將其全部保存為一個(如果可能)并將其全部加載為一個,因為我有 Angular 前端期望它并將其發送回編輯。
如果缺少某些內容或不容易理解,我會嘗試更好地回答和編輯。感謝所有評論。
我希望有人已經解決了這樣的場景,但是我在檔案中找不到任何類似這樣的案例。請幫忙。
編輯:我已將結構更改為更像我給@grek40 的示例(謝謝)。我不能發布真正的課程,但這個例子應該幾乎是 1:1 的問題,我有。
uj5u.com熱心網友回復:
基本上,OwnsMany這是一種特殊的關系,當您有多個具有導航屬性的物體到同一個目標時,這種關系就不適合了。在這種情況下,您應該使用HasMany關系。
當您對同一個物體有多個參考(例如TransitionOptions屬于 someCurrentStep并指向 some NextStep)時,請使用 FluentApi 或用 注釋InversePropertyAnnotation,而不是用ForeignKeyAnnotation。
一般來說,我建議你使用更流暢的 api 配置和更少的基于注釋的配置——它更容易維護。
這是基于您的問題的一些示例代碼。
模型類
public class Story
{
public int Id { get; set; }
public List<Step>? Steps { get; set; }
public List<Variable>? Variables { get; set; }
}
public class Variable
{
public int Id { get; set; }
public int StoryId { get; set; }
public string? Value { get; set; }
public Story? Story { get; set; }
public List<Change>? Changes { get; set; }
}
public class Step
{
public int Id { get; set; }
public int StoryId { get; set; }
public Story? Story { get; set; }
public List<TransitionOption>? TransitionOptions { get; set; }
}
public class TransitionOption
{
public int Id { get; set; }
public int StepId { get; set; }
public int? NextStepId { get; set; }
public Step? CurrentStep { get; set; }
public Step? NextStep { get; set; }
public List<Change>? Changes { get; set; }
}
public class Change
{
// If combination of TransitionOptionId and VariableId is unique,
// you can use them as composite key instead
public int Id { get; set; }
public int TransitionOptionId { get; set; }
public int VariableId { get; set; }
public Variable? Variable { get; set; }
public TransitionOption? TransitionOption { get; set; }
}
物體配置類
internal class StoryConfiguration : IEntityTypeConfiguration<Story>
{
public void Configure(EntityTypeBuilder<Story> builder)
{
builder.HasMany(x => x.Variables)
.WithOne(x => x.Story)
.HasForeignKey(x => x.StoryId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasMany(x => x.Steps)
.WithOne(x => x.Story)
.HasForeignKey(x => x.StoryId)
.OnDelete(DeleteBehavior.Cascade);
}
}
internal class VariableConfiguration : IEntityTypeConfiguration<Variable>
{
public void Configure(EntityTypeBuilder<Variable> builder)
{
builder.HasMany(x => x.Changes)
.WithOne(x => x.Variable)
.HasForeignKey(x => x.VariableId)
.OnDelete(DeleteBehavior.Cascade);
}
}
internal class StepConfiguration : IEntityTypeConfiguration<Step>
{
public void Configure(EntityTypeBuilder<Step> builder)
{
builder.HasMany(x => x.TransitionOptions)
.WithOne(x => x.CurrentStep)
.HasForeignKey(x => x.StepId)
.OnDelete(DeleteBehavior.Cascade);
// No navigation property in Step for TransitionOptions pointing
// to this as NextStep.
// It would also be possible to define such a property and mention it
// in HasMany
builder.HasMany<TransitionOption>()
.WithOne(x => x.NextStep)
.HasForeignKey(x => x.NextStepId)
// If next step is deleted, only disconnect referencing TransitionOptions
.OnDelete(DeleteBehavior.SetNull);
}
}
internal class TransitionOptionConfiguration : IEntityTypeConfiguration<TransitionOption>
{
public void Configure(EntityTypeBuilder<TransitionOption> builder)
{
builder.HasMany(x => x.Changes)
.WithOne(x => x.TransitionOption)
.HasForeignKey(x => x.TransitionOptionId)
.OnDelete(DeleteBehavior.Cascade);
}
}
在方法中應用配置OnModelCreating。
使用 1 創建整個故事結構的示例方法SaveChanges
public async Task InitDb(MyDatabase db)
{
var variable1 = new Variable
{
Value = "1st Value"
};
db.Stories?.Add(new Story
{
Variables = new List<Variable>
{
variable1
},
Steps = new List<Step>
{
new Step
{
TransitionOptions = new List<TransitionOption>
{
new TransitionOption
{
Changes = new List<Change>
{
new Change
{
Variable=variable1
}
}
}
}
}
}
});
await db.SaveChangesAsync();
}
希望此示例顯示您所描述的結構所需的一切。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/471026.html
上一篇:EntityFrameworkCore關系并使用代碼優先方法中的查找獲取詳細資訊
下一篇:“物件”型別上不存在屬性“邊界”
