几年前,我写了一篇关于使用 Entity Framework 将枚举保存到数据库的文章。 它能够将枚举作为字符串保存到数据库中,并且在从数据库中读取时能够获取该字符串并正确填充枚举。 它工作正常,但感觉有点老套。
使用 Entity Framework Core,有一种更简洁、更好的方法可以使用值转换来执行此操作。
假设我们有一个包含两个枚举的Address
- AddressType
和 DeliveryPreference
。
public partial class Address
{
public int AddressId { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public AddressType AddressType { get; set; }
public DeliveryPreference DeliveryPreference { get; set; }
}
我们可以将枚举作为字符串或整数保存到数据库中,并在读回它们时填充枚举! 这是实现的方法。
表
我的表格看起来像这样
如您所见,AddressType
存储为 int
,而 DeliveryPreference
存储为字符串。
当你运行应用程序时,它应该为你创建数据库和表,但如果你没有正确设置权限,这里是创建它的脚本。
CREATE TABLE [dbo].[Address] (
[AddressId] INT IDENTITY (1, 1) NOT NULL,
[Line1] VARCHAR (50) NOT NULL,
[Line2] VARCHAR (50) NOT NULL,
[AddressType] INT NOT NULL,
[DeliveryPreference] VARCHAR (50) NOT NULL,
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([AddressId] ASC)
);
将枚举保存为字符串
首先让我们看看将 DeliveryPreference
枚举保存为string
。
在我们构建实体的上下文中,我有您期望的 AddressId
、Line1
和 Line2
的常见内容。 但是 DeliveryPreference
有点不同。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Address>(entity =>
{
entity.Property(e => e.AddressId).ValueGeneratedOnAdd();
entity.Property(e => e.Line1)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.Line2)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.DeliveryPreference)
.HasMaxLength(50)
.HasConversion(x => x.ToString(), // to converter
x => (DeliveryPreference) Enum.Parse(typeof(DeliveryPreference), x));// from converter
//snip..
DeliveryPreference
使用 HasConversion
方法,向其传递两个参数。 第一个参数是 convert to provider
表达式,顾名思义,它将我们对象中的值转换为您将存储在数据库中的类型。
第二个是 convert from provider
表达式,它将数据库中的类型转换为您的类中的类型。
在此示例中,我将枚举转换为字符串以存储在数据库中,当从数据库中检索时,我将存储的字符串转换为 DeliveryPreference 枚举。
将枚举保存为int
对于第二个枚举,AddressType
,我不需要明确地将它从枚举转换为 int
,Entity Framework 会自动执行此操作(正如我在这条推文中指出的那样)。 但我将它作为示例包含在内,以防您需要类似这样的东西来进行其他一些显式转换。
在此示例中,我将枚举转换为 int
以存储在数据库中,当从数据库中检索时,我将存储的 int
转换为 AddressType
枚举。
// this is a continuation of the OnModelCreating method
entity.Property(e => e.AddressType)
.HasConversion(x => (int) x, x => (AddressType) x);