如何在C#中使用单例类作为ENUM的替代?

时间:2013-06-15 21:04:21

标签: c# .net entity-framework ef-code-first

我有一个名为“Card”的课程,其中包含“Sides”。

两个实体都有一个阶段 - 三个阶段之一。

这是我的实体:

public class Card
{
    public Card()
    {
        Sides = new Collection<Side>();
        Stage = Stage.ONE;
    }

    [Key]
    [Required]
    public virtual int CardId { get; set; }

    [Required]
    public virtual Stage Stage { get; set; }

    [Required]
    [ForeignKey("CardId")]
    public virtual ICollection<Side> Sides { get; set; }
}

这是我的 Side 实体:

public class Side
{
    public Side()
    {
        Stage = Stage.ONE;
    }

    [Key]
    [Required]     
    public virtual int SideId { get; set; } 

    [Required]
    public virtual Stage Stage { get; set; }

    [Required]
    public int CardId { get; set; }

    [ForeignKey("CardId")]
    public virtual Card Card { get; set; }

}

这是我的舞台实体:

public class Stage
{
    // Zero
    public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
    // Ten seconds
    public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");

    public static IEnumerable<Stage> Values
    {
        get
        {
            yield return ONE;
            yield return TWO;
        }

    }

    public int StageId { get; set; }
    private readonly TimeSpan span;
    public string Title { get; set; }

    Stage(TimeSpan span, string title)
    {
        this.span = span;
        this.Title = title;
    }

    public TimeSpan Span { get { return span; } }
}

我注意到当我创建一个新的Card或Side时,Stage表会获得一个标题为“ONE”的新条目和一个自动递增的ID - 这不应该发生。 Stage表中应该只有两个阶段。舞台基本上是一个带有一些值的枚举 - 标题和跨度。

如何防止添加新阶段?我正在使用EF CodeFirst,以防它相关。

更新基于Honza的回复:

public class Stage
{
    [Key]
    public virtual int StageId { get; set; }
    public string Name { get; set; }
    public TimeSpan Span { get; set; }

    public static class Values
    {
        public static readonly Stage ONE = new Stage()
            {
                StageId = 0,
                Name = "ONE",
                Span = new TimeSpan(0, 0, 0)
            };
        public static readonly Stage TWO = new Stage()
        {
            StageId = 1,
            Name = "TWO",
            Span = new TimeSpan(0, 0, 10)
        };
    }

虽然它仍在自动增加 - 我缺少什么?

1 个答案:

答案 0 :(得分:0)

每次实例化ONETWO时,都会在没有StageId的情况下创建它们。实体框架需要提示能够告诉它们与已存在的Stage条目相等。设为StageId密钥,在创建这些实例时指定。这样,EF可以告诉他们已经在数据库中并引用现有的而不是创建新的。

这是一种非常“硬编码”的方法。

可能更好,而不是以这种方式创建实例,在DB中查找它们(基于我猜的标题),如果它们不存在则创建它们。这样的操作可能不适合静态字段初始化,因为它例如你得到一个SQL超时异常(DB可能在另一台机器上,网络可能打嗝......),整个类型将无法加载,这是一个处理凌乱的情况。

您可以将实例保存在使用Stages的对象中,而不是静态字段。这将使与DB相关的作业和错误handlind更容易,并允许更好的可测试性(您可以使用ONETWO的任何实例,而不是硬编码的实例。