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



如何在实体框架核心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");
}

id生成策略在OnModelCreating:中设置

builder.Entity<TestStatus>()
.Property(s => s.Id)
.ValueGeneratedNever();

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

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

根据使用情况,我得到以下错误之一:

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

SqlException:违反PRIMARY KEY约束"PK_Status"。无法在对象"dbo.Statues"中插入重复的键。重复的键值为(1)。语句已终止。

我理解这个错误。EF认为我正在尝试创建一个具有相同Id的新实例。我如何告诉EF这些实例应该被视为相同?我可以通过脱离类型安全枚举模式来解决这个问题。如果可能的话,我只想让它与模式一起工作。它在rc1中工作。

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

[Required]
protected string ObjectTypeValue { get; set; }
[NotMapped]
public ObjectType Type
{
get { return ObjectType.Parse(ObjectTypeValue); }
set { ObjectTypeValue = value.Print(); }
}

出于某些原因,我使用字符串作为Id,但您可以使用任何您喜欢的类型。

最新更新