我目前正在做一個代碼優先的小專案:我必須創建一個電影資料庫,像往常一樣,每部電影可以有多個流派 (m:n)。由于流派是恒定的,我決定創建一個包含所有流派的列舉流派。
在Movie表格中,我有一個流派串列(列舉)。顯然這是錯誤的,因為您不能在資料庫中存盤列舉串列。
于是我開始尋找答案。我遇到了很多解決方案,不幸的是沒有一個真正幫助我。所以我決定問這個問題。我知道這可能是重復的,但其他解決方案并沒有真正的幫助。
我發現的一些解決方案是Flags和SmartEnum。
我兩個都試過,但沒有真正奏效。你能不能看看我的代碼,告訴我我做錯了什么,或者是否有另一種方法來轉換列舉串列。
電影:
class Serie
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(255)]
public string Titel { get; set; } = "";
public virtual List<Genres> Genres { get; } = new();
}
流派:
public sealed class Genres : SmartEnum<Genres>
{
public static readonly Genres Drama = new(name: "Drama", value: 1);
public static readonly Genres Crime = new(name: "Crime", value: 2);
...
private Genres(string name, int value) : base(name, value)
{ }
}
PS:我知道我可以用額外的課程來做,但我想用列舉來做。
uj5u.com熱心網友回復:
EF 可以很好地與 Enums 一起使用,盡管我不會認為您使用電影流派的示例是列舉的一個很好的候選者,因為可以添加新的流派。SmartEntity 的使用只是一個類包裝器。
您的流派示例是多對多關系,因此查看資料庫方面,您會得到類似的資訊:
Genres
- GenreId (PK)
- Name
Series
- SeriesId (PK)
SeriesGenres
- SeriesId (PK, FK)
- GenreId (PK, FK)
Genre 是一個簡單的類,所以老實說,用像 SmartEnum 這樣的結構類來包裝它并沒有真正的好處。在一天結束時,您會希望 EF 像對待任何其他物體一樣對待它,以便您可以有效地對其進行查詢。EF Core 5 可以容納多對多關系,而無需定義 SeriesGenre 物體,其中一個 Series 只包含一個 Genre 集合,然后配置一個HasMany(x => x.Genres).WithMany()關系以及 SeriesGenre 表和 FK 的配置。EF 可以處理幕后的其余作業。
列舉的一個更好的例子是類似 Status 的東西,其中您需要一組固定的狀態,業務規則邏輯將根據這些狀態進行操作,并且除非系統更新以說明新狀態,否則不會更改。例如:
///<summary>
/// Enumeration for order statuses. Ensure this matches the OrderStatuses table.
///</summary>
public enum OrderStatus
{
None = 0,
Pending = 1,
Packing = 2,
Review = 3,
Shipped = 4,
Delivered = 100
}
在這種情況下,訂單將記錄任何時間點的狀態。業務邏輯將取決于當前的狀態狀態。我們希望將訂單記錄存盤為 Status,但仍要確保我們的資料庫具有參照完整性,因此我們將擁有一個 Statuses 表,其中對應的 OrderStatusIds 與 Enum 中的內容相匹配。Orders 表中的 OrderStatusId 列然后可以在 OrderStatuses 表上有一個 FK 約束,以保持資料庫中的參照完整性。OrderStatus 永遠不會獲得物體宣告。
我在這樣做時的主要建議是:
- 列舉持有表 PK 列不應使用自動遞增,而是使用顯式 ID 來匹配 Enum。
- 同樣,每個值的列舉應該是明確的,而不是依賴于自動增量。
- 表和列舉應記錄在案以參考它們的相互依賴關系。
uj5u.com熱心網友回復:
這不是真正的enum問題,而是您想要對多對多關系建模的事實。如果您需要存盤int或的串列string,則相同。
要么打破良好做法,將同一部電影的多行存盤在電影表中(電影的每種型別各有一行)。在這種情況下,您將直接將 an 存盤enum在資料庫中。那真的會很丑。
或者您正確建模,這意味著您需要一個表格來存盤您的流派。該表可以以經典方式構建,具有主鍵 (Id) 和值(流派列舉值)。您甚至可以使用 的int表示enum作為主鍵,但我認為這樣做沒有任何好處。
要enum使用 EF Core將s 作為屬性存盤在資料庫中,請使用預定義或內置轉換器。
請參閱https://docs.microsoft.com/en-us/ef/core/modeling/value-conversions?tabs=fluent-api#pre-defined-conversions
您需要一個流派列舉和一個流派類來進行映射:
public enum GenreEnum
{
Drama,
Western,
//...
}
public class Genre
{
public int Id { get; set; }
public GenreEnum Name { get; set; }
// And other properties needed.
}
進而
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Genre>()
.Property(e => e.Name)
.HasConversion<string>();
}
這甚至可以通過屬性更簡單地完成:
public enum GenreEnum
{
Drama,
Western,
//...
}
public class Genre
{
public int Id { get; set; }
[Column(TypeName = "nvarchar(24)")]
public GenreEnum Name { get; set; }
// And other properties needed.
}
當然,你需要一個DbSet<Genre>和DbSet<Movie>,和許多人之間有很多的關系Movie和Genre。
But I'm not sure I'd use this as a solution. New genres might need to be added in the future, and a simple string instead of an enum might be better.
EDIT
You could store a string that contains some form of a serialization of your list of enum:
For instance "Western; Drama", or a JSON representation
An be able de deserialize it, but again that would be ugly.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/359173.html
上一篇:ajax提交后如何防止頁面重繪
