2010-10-12 4 views
4

У меня есть модель, которая должна быть в одном из следующих взаимоисключающих состояний: Нового, In Progress или Закрытая.Флаг Enum и взаимоисключающие Enum с перекрытием значения

Приложение позволяет пользователю сохранять запись, а затем извлекать их, предоставляя список состояний соответствия.

Я унаследовал базу данных SQL, где состояние хранится как целое число, представляющее побитовые флаги. Мне нужно вызвать процедуру, которая выполняет согласование с побитовым действием:

CREATE PROCEDURE SearchByState 
    @MatchingStates  int 
AS 
BEGIN 
    SELECT Id, State 
    FROM Records 
    WHERE @MatchingStates & State > 0 
END; 
GO 

Все это в порядке.

Теперь, в реализации C#, это довольно ясно, что я должен определить флаги представляют собой комбинацию соответствующих состояний в запросе:

[Flags] 
public enum States 
{ 
    None = 0x0, 
    New= 0x1, 
    InProgress = 0x2, 
    Closed = 0x4, 
    All = New | InProgress | Closed 
} 

Вопрос заключается в том, что модель записи должна иметь свойство который представляет собой одно государство.

Вопрос заключается в том, что должно быть типом государственной собственности модели этой записи:

1) Просто используйте перечисление флаги:

public class Record 
{ 
    public int Id { get; set; } 

    // Must ensure the value is equal to one of 
    // States.New, States.InProgress, or States.Closed 
    public States State { get; set; } 
} 

2) Определить новый тип перечисления для взаимоисключающего состояния:

public enum State 
{ 
    New, 
    InProgress, 
    Closed 
} 

public class Record 
{ 
    public int Id { get; set; } 

    // Must be stored as the value of one of 
    // States.New, States.InProgress, or States.Closed 
    public State State { get; set; } 
} 

недостаток # 1 семантический: перечисление Штаты представляет собой комбинацию состояний, а не единое государство.

Недостаток # 2 практичен: при хранении состояния я должен определить базовое значение, которое необходимо сохранить.

Можете ли вы представить себе способ представления всего этого, минимизируя эти недостатки?

ответ

4

Я бы оставил его как единое, не-фламенковое перечисление.

Когда вы передаете это процедуре, вы можете построить целое число из перечисления с помощью побитового или (|) или даже просто добавить значения (cast to int). Я бы постарался не «ломать» вашу логику, чтобы сделать один старый запрос, а вместо этого переработать код, который вызывает запрос для обработки необычных требований.

Это сохраняет код чистым везде. «Состояние» в вашем случае не должно быть перечислением флага - существует только одно возможное состояние.

+0

Обратите внимание также, что OP будет нуждаться в дополнительной проверке в своем сеттере - вместо использования авто-имущества - если они хотят обеспечить это. С примером кода из вопроса нет ничего, что помешало бы мне сделать что-то вроде 'myRecord.State = (State) 123456;' – LukeH

+0

@LukeH: Правда, но это правда с любым типом перечисления, перечислением флага или нет. –

1

Я бы пошел с опцией № 2, а затем изменил ваши операторы Get/Set, чтобы каждый раз определять базовое значение. Таким образом, это делается для вас каждый раз, когда вы вызываете свойства. Код один раз, и все готово.