如何在实体框架核心rc2中实现类型安全的枚举模式

Eri*_*ott 5 .net c# enums entity-framework entity-framework-core

如何在实体框架核心rc2中实现类型安全的枚举模式

public class TestStatus
{
    [Column("Id")]
    public int Id { get; private set; }

    [Column("Description")]
    public string Description { get; private set; }

    [Column("LongDescription")]
    public string LongDescription { get; private set; }

    private TestStatus(int id
        , string description
        , string longDescription)
    {
        Id = id;
        Description = description;
        LongDescription = longDescription;
    }

    public TestStatus() { }

    public static readonly TestStatus Active = new TestStatus(1, "Active", "Active Long Description");
    public static readonly TestStatus Pending = new TestStatus(2, "Pending", "Pending Long Description");
    public static readonly TestStatus Cancelled = new TestStatus(3, "Cancelled", "Cancelled Long Description");
}
Run Code Online (Sandbox Code Playgroud)

id生成策略在OnModelCreating中设置:

builder.Entity<TestStatus>()
    .Property(s => s.Id)
    .ValueGeneratedNever();
Run Code Online (Sandbox Code Playgroud)

这是一个简化的示例,但是实际代码在rc1中有效。升级到rc2时,我必须添加Column属性,以便可以映射属性(我认为这是由于私有setter的缘故)。尝试分配typesafe枚举值时:

var i = new TestItem
{
    Name = "Test Item 2",
    Status = TestStatus.Active
};
_context.Items.Add(i);
_context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

根据使用情况,出现以下错误之一:

InvalidOperationException:无法跟踪实体类型“ TestStatus”的实例,因为已经跟踪了具有相同键的该类型的另一个实例。对于新实体,请考虑使用IIdentityGenerator生成唯一的键值。

要么

SqlException:违反PRIMARY KEY约束'PK_Statuses'。无法在对象“ dbo.Statuses”中插入重复键。重复键值为(1)。该语句已终止。

I understand the error. EF thinks that I am trying to create a new instance with the same Id. How can I tell EF that these instances should be considered the same? I can workaround this by moving away from the typesafe enum pattern. I would just like to make it work with the pattern if possible. It was working in rc1.

Sam*_*Sam 5

由于您使用的是类型安全模式,因此无需保留整个对象。只需存储id并创建一个包装,如下所示:

    [Required]
    protected string ObjectTypeValue { get; set; }

    [NotMapped]
    public ObjectType Type
    {
        get { return ObjectType.Parse(ObjectTypeValue); }
        set { ObjectTypeValue = value.Print(); }
    }
Run Code Online (Sandbox Code Playgroud)

由于某些原因,我将字符串用作ID,但是您可以使用任何喜欢的类型。