2013-06-16 3 views
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) 
     }; 
} 

Но всякий раз, когда я создаю новый экземпляр объекта, который имеет этап, новый Этап добавляется к db. Мне просто нужно несколько постоянных этапов.

Использование этапа:

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

ответ

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 разумно прямо сказать, чтобы свойство просто хранили ».Значение»свойства, и вы можете подключить его обратно, когда вы загружаете значение, имея его называют:.

Stage.FromValue<Stage>(intValue); 
+0

Черт, спасибо, чувак, это невероятно. – SB2055

+0

Нет проблем. Я использовал его кучи, и это так удобно для такого рода ситуаций. – Rophuine

1

Держите Stage как свойство вашей сущности, использовать его так, как вы делаете, и добавить

Ignore(x => x.Stage)

вашему отображения. Это игнорирует это свойство при сопоставлении с вашей базой данных.

Редактировать: Я неверно истолковал вопрос.

Если вы хотите только разные этапы в своей базе данных, вы должны поместить этапы в свою таблицу с идентификатором и обратиться к этому идентификатору через отношения. Каждый объект будет содержать дополнительную ссылку, и вам нужно будет определить отношения для них.

Это вы что искали?

+0

Спасибо Я хотел бы свойство Stage храниться в БД, я просто не необходимо создать повторяющиеся этапы. Мой объект в настоящее время также содержит этап ... но создание нового объекта создает новый этап, которого он не должен. Обновил мое сообщение, чтобы показать объект, который использует этап – SB2055

+0

Обновлено мое сообщение с дополнительным предложение –

Смежные вопросы