3

在代码中我想做这样的事情:

item.Stage = Stage.Values.ONE;

其中 Stage.Values.ONE 代表一些预定义的阶段:

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

我正在处理 EF CodeFirst... 我有很多阶段要定义。我不确定是否应该将数据存储在数据库中,或者在 dbContext 中,或者什么,但我正在寻找最简单的实现。

我试过这个:

我尝试了以下(定义两个常量):

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

但是,每当我创建具有 Stage 的实体的新实例时,都会将一个新 Stage 添加到数据库中。我只需要几个不变的阶段。

舞台使用:

public class Side
{
    public Side()
    {
        Stage = Stage.Values.ONE;  // Adds new Stage to DB, when it should be a reference to the one I defined above
    }
    public virtual Stage Stage { get; set; }
}
4

2 回答 2

2

它看起来有点像一个枚举,我之前曾多次使用过一种“扩展枚举”模式并取得了一些成功。因为您在代码中引用这些值,所以将它们也存储在数据库中可能没有意义,但如果需要,它是可能的。

该技术在此处详细描述:http: //lostechies.com/jimmybogard/2008/08/12/enumeration-classes/

基本上,您创建一个基类,它提供许多类似于枚举的服务,然后创建您的“枚举类”,您从它继承并提供一堆静态实例,这些实例调用具有您需要的许多属性的构造函数.

为了避免链接失效,这里是要使用的基类(只需将整个类放入您的项目中的某个地方),然后向下滚动以获取您自己的代码。

public abstract class Enumeration : IComparable
{
    private readonly int _value;
    private readonly string _displayName;

    protected Enumeration()
    {
    }

    protected Enumeration(int value, string displayName)
    {
        _value = value;
        _displayName = displayName;
    }

    public int Value
    {
        get { return _value; }
    }

    public string DisplayName
    {
        get { return _displayName; }
    }

    public override string ToString()
    {
        return DisplayName;
    }

    public static IEnumerable<T> GetAll<T>() where T : Enumeration, new()
    {
        var type = typeof(T);
        var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);

        foreach (var info in fields)
        {
            var instance = new T();
            var locatedValue = info.GetValue(instance) as T;

            if (locatedValue != null)
            {
                yield return locatedValue;
            }
        }
    }

    public override bool Equals(object obj)
    {
        var otherValue = obj as Enumeration;

        if (otherValue == null)
        {
            return false;
        }

        var typeMatches = GetType().Equals(obj.GetType());
        var valueMatches = _value.Equals(otherValue.Value);

        return typeMatches && valueMatches;
    }

    public override int GetHashCode()
    {
        return _value.GetHashCode();
    }

    public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)
    {
        var absoluteDifference = Math.Abs(firstValue.Value - secondValue.Value);
        return absoluteDifference;
    }

    public static T FromValue<T>(int value) where T : Enumeration, new()
    {
        var matchingItem = parse<T, int>(value, "value", item => item.Value == value);
        return matchingItem;
    }

    public static T FromDisplayName<T>(string displayName) where T : Enumeration, new()
    {
        var matchingItem = parse<T, string>(displayName, "display name", item => item.DisplayName == displayName);
        return matchingItem;
    }

    private static T parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration, new()
    {
        var matchingItem = GetAll<T>().FirstOrDefault(predicate);

        if (matchingItem == null)
        {
            var message = string.Format("'{0}' is not a valid {1} in {2}", value, description, typeof(T));
            throw new ApplicationException(message);
        }

        return matchingItem;
    }

    public int CompareTo(object other)
    {
        return Value.CompareTo(((Enumeration)other).Value);
    }
}

现在您的代码将如下所示:

public class Stage : Enumeration
{
    public TimeSpan TimeSpan { get; private set; }

    public static readonly Stage One
        = new Stage (1, "Stage one", new TimeSpan(5));
    public static readonly Stage Two
        = new Stage (2, "Stage two", new TimeSpan(10));
    public static readonly Stage Three
        = new Stage (3, "Stage three", new TimeSpan(15));

    private EmployeeType() { }
    private EmployeeType(int value, string displayName, TimeSpan span) : base(value, displayName) 
    { 
        TimeSpan = span;
    }
}

完成设置后,您可以将 .Value 存储在数据库中。恐怕我还没有在 EF 中做到这一点,但在 nHibernate 中,告诉属性只存储属性的“.Value”是相当直接的,并且您可以在加载值时将其连接回来让它调用:

Stage.FromValue<Stage>(intValue);
于 2013-06-16T01:40:24.040 回答
1

将其Stage作为您的实体的属性,按照您的方式使用它并添加

Ignore(x => x.Stage)

到您的映射。这将在映射到您的数据库时忽略此属性。

编辑:我误解了这个问题。

如果您只需要数据库中的不同阶段,您应该将这些阶段放在他们自己的带有 ID 的表中,并通过关系引用该 ID。每个实体都会有一个额外的引用,您必须为它们定义关系。

这是你要找的吗?

于 2013-06-16T01:16:42.730 回答