[英]Is it possible in EF Core to make a one-way navigation property required?
我正在開發一個基本的群聊系統,為此我創建了這些類:
public class Role
{
public Guid Id { get; set; };
public string Username { get; set; }
}
public class Message
{
public Guid Id { get; set; };
public Role Author { get; set; }
public Conversation Conversation { get; set; }
public DateTime Date { get; set; }
public string Text { get; set; }
}
public class Conversation
{
public Guid Id { get; set; };
public IList<ConversationParticipant> ConversationParticipants { get; set; };
public IList<Message> Messages { get; set; };
}
public class ConversationParticipant
{
public Conversation Conversation { get; set; }
public Role Role { get; set; }
}
我們在遷移中使用 EF Core 3.1 Code-First。
我正在尋找一種使Message.Author
成為必需屬性的方法,這應該導致表Message
中的列被創建為AuthorId NOT NULL
。
我試過了:
public static void Map(this EntityTypeBuilder<Message> builder)
{
builder.HasOne(m => m.Author);
}
由於這是使用 Add-Migration 和 Update-Database 應用的,因此會創建數據庫列AuthorId
,但允許使用NULL
。
似乎沒有我可以在 HasOne() 之后添加的方法IsRequired()
HasOne()
。
我也試過:
public static void Map(this EntityTypeBuilder<Message> builder)
{
builder.Property(m => m.Author).IsRequired();
}
但這沒有說
屬性“Message.Author”屬於“角色”類型,當前數據庫提供程序不支持。 更改屬性 CLR 類型或使用“[NotMapped]”屬性或使用“OnModelCreating”中的“EntityTypeBuilder.Ignore”忽略該屬性。
執行.HasOne(...)
后跟 .Property( .Property(...).IsRequired()
也不起作用:
“作者”不能用作實體類型“消息”的屬性,因為它被配置為導航。
我設法通過以下方式使Message.Conversation
成為必需:
public static void Map(this EntityTypeBuilder<Conversation> builder)
{
builder.HasMany(c => c.Messages) // A conversation can have many messages
.WithOne(e => e.Conversation) // Each message belongs to at most 1 conversation
.IsRequired(); // A message always has a conversation
}
但是,我不想讓Role
知道消息,因為我永遠不想直接從角色中檢索消息(這將通過對話和參與者發生)。
我的最終問題是:有沒有一種方法可以使Message.Author
成為必需(非空),而無需將Message
和Role
與Role
中的 Messages 屬性以完全一對多的關系鏈接在一起?
將Role
的外鍵添加到Message
然后要求該屬性不是 null 怎么樣? 就像是:
// MessageConfiguration.cs
builder.Property(b => b.RoleId).IsRequired()
雖然@Ben Sampica 的回答很有幫助並讓我到達了我需要的地方,但@Ivan Stoev 的評論提供了細節和清晰度,讓我認為更全面的答案會很有用。
有多種方法可以在生成的表中使外鍵列成為必需(NOT NULL)。
最簡單的是將[Required]
放在導航屬性上:
public class Message { //... [Required] public Role Author { get; set; } //... }
這將導致 EF 創建Guid
類型的影子屬性AuthorId
,因為 Message.Author 是 Role 並且 Role.Id 是 Guid 類型。 在 SQL 服務器的情況下,這會導致UNIQUEIDENTIFIER NOT NULL
。
如果省略[Required]
則 EF 將使用Guid?
,這會導致UNIQUEIDENTIFIER NULL
,除非您應用其他選項之一。
您可以使用類型不能為 null 的顯式 Id 屬性:
public class Message { //... public Guid AuthorId { get; set; } public Role Author { get; set; } //... }
注意 (i) - 這僅在您遵循 EF Core 影子屬性命名規則時才有效,在這種情況下,這意味着您必須將 Id 屬性命名為nameof(Author) + nameof(Role.Id)
== AuthorId
。
注意 (ii) - 如果有一天您決定重命名Author
或Role.Id
但忘記相應地重命名AuthorId
,這將中斷。
如果您不能或不想更改 Model class,那么您可以告訴 EF Core 它需要按要求處理 shadow 屬性:
builder.Property("AuthorId").IsRequired();
與2中列出的相同的注釋適用,此外您現在可以使用nameof()
來減少工作量和風險。
最后我決定使用[Required]
方法,因為
這有時可能適用,但並非總是如此:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.