【问题标题】:How to implement typesafe enum pattern in entity framework core rc2如何在实体框架核心 rc2 中实现类型安全枚举模式
【发布时间】:2016-05-25 13:37:29
【问题描述】:

如何在实体框架核心rc2中实现typesafe enum pattern

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");
}

在 OnModelCreating 中设置 id 生成策略:

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

这是一个简化的例子,但真正的代码是在 rc1 中工作的。升级到 rc2 时,我必须添加 Column 属性以便映射属性(我假设这是因为私有 setter)。尝试分配类型安全枚举值时:

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

根据用例,我会遇到以下错误之一:

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

或者

SqlException:违反主键约束“PK_Statuses”。无法在对象“dbo.Statuses”中插入重复键。重复键值为 (1)。声明已终止。

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

【问题讨论】:

  • 为什么TestStatus 对象都具有相同的Id
  • @noox 这是一个错字。我已经编辑了这个问题来解决它。谢谢!

标签: c# .net entity-framework enums entity-framework-core


【解决方案1】:

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

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

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

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

【讨论】:

  • 我花了一两分钟来理解@sam 提出的答案。对于任何可能为此苦苦挣扎的人,他的意思是在使用类型安全枚举的类型上创建一个属性,该枚举只存储值(或 id 或任何你称之为的)。这让 EF 很高兴,因为它所要做的就是存储一个简单的类型。接下来,只需创建一个“包装器”,通过在您的枚举上调用某种.Parse 方法将类型安全枚举公开为一个对象。达达!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 2022-11-18
  • 2020-01-26
  • 1970-01-01
相关资源
最近更新 更多