![](/img/trans.png)
[英]Using EF's Enum's in Lightswitch in ComboBox/DropDown list control
[英]How to store a List of enum using EF 5
我目前正在做一个代码优先的小项目:我必须创建一个电影数据库,并且像往常一样,每部电影可以有多个类型 (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:我知道我可以用额外的 class 来做到这一点,但我想用枚举来做到这一点。
这并不是真正的enum
问题,而是您想要 model 多对多关系的事实。 如果您需要存储int
或string
的列表,那将是相同的。
要么你打破良好的做法,并在你的电影表中存储同一部电影的几行(电影的每种类型都有一行)。 在这种情况下,您将直接在数据库中存储一个enum
。 那真的很难看。
或者你的 model 是正确的,这意味着你需要一个存储你的流派的表。 该表可以以经典方式构建,具有主键 (Id) 和值(流派枚举值)。 您甚至可以使用enum
的int
表示形式作为主键,但我认为这样做没有任何好处。
要使用 EF Core 将enum
作为属性存储在数据库中,请使用预定义或内置转换器。
您需要一个流派枚举和一个流派 class 用于映射:
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
之间的多对多关系。
但我不确定我是否会将其用作解决方案。 将来可能需要添加新的流派,一个简单的string
而不是enum
可能会更好。
编辑
您可以存储一个string
,其中包含某种形式的enum
列表的序列化:
例如“西方;戏剧”,或 JSON 表示
可以反序列化它,但这又是丑陋的。
EF 可以很好地与 Enums 一起工作,但我不认为您使用电影流派的示例是一个很好的枚举候选者,因为可以添加新的流派。 SmartEntity 的使用只是一个 class 包装器。
您的流派示例是多对多关系,因此查看数据库方面,您将有如下内容:
Genres
- GenreId (PK)
- Name
Series
- SeriesId (PK)
SeriesGenres
- SeriesId (PK, FK)
- GenreId (PK, FK)
流派是一个简单的 class,所以说实话,用像 SmartEnum 这样的结构 class 包装它并没有真正的好处。 归根结底,您会希望 EF 像对待任何其他实体一样对待它,以便您可以有效地查询它。 EF Core 5 可以适应多对多关系,而无需定义 SeriesGenre 实体,其中 Series 仅具有 Genre 的集合,然后配置有HasMany(x => x.Genres).WithMany()
关系和SeriesGenre 表和 FK 的配置。 EF可以在幕后照顾rest。
枚举的一个更好的例子是状态,您需要一组固定的状态,业务规则逻辑将根据这些状态进行操作,并且除非系统更新以考虑新状态,否则它们不会更改。 例如:
///<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
}
在这种情况下,订单将记录任何时间点的状态。 业务逻辑将取决于当前状态 state。 我们希望将订单记录存储为状态,但仍要确保我们的数据库具有引用完整性,因此我们将有一个状态表,其中对应的 OrderStatusIds 与枚举中的内容匹配。 然后,Orders 表中的 OrderStatusId 列可以对 OrderStatuses 表具有 FK 约束,以保持数据库中的引用完整性。 OrderStatus 永远不会获得实体声明。
我这样做的主要建议是:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.