2009-07-24 14 views
5

OK, entonces tengo un campo de base de datos de tipo char (1) que tiene un número pequeño de posibles códigos de estado (por ejemplo, 'F' = Fallo, 'U' = Desconocido, etc.). Me gustaría tener una clase enum C# que corresponda a estos estados. Puedo hacer:¿Cómo implementar C# enum para el campo enumerado de la base de datos char (1)?

public enum StatusCode : byte { 
    Unknown = (byte) 'U', 
    Failure = (byte) 'F', 
    // etc. 
} 

Hasta ahora todo bien. Pero en la DataTable devuelta desde la base de datos, los valores de columna son instancias de System.Data.SqlTypes.SqlString. Obviamente, hay algunos problemas de conversión de una cadena C# (o incluso un carácter C#) a un byte C# (ya que C# char es realmente un punto de código UTF-16). Pero en este caso, sé que los valores están limitados a un conjunto pequeño, y el código debería arrojar una excepción si aparece un valor fuera de este conjunto.

Teniendo esto en cuenta, ¿cuál es la mejor manera de hacerlo? ¿Es seguro convertir un SqlString en un byte? ¿Sería mejor Convert.ToByte()? ¿Sería mejor simplemente usar una construcción de interruptor/caja para cruzar los valores en la enumeración?

Estoy buscando la "mejor" forma de hacerlo, no solo en términos de obtener los resultados correctos sino también por la claridad del código. Supongo que también podría usar algunas constantes como

public const char UnknownStatus = 'U'; 
public const char FailureStatus = 'F'; 

Pero prefiero usar una enumeración si es posible. ¿Alguna idea?

Editar: Para aclarar lo que quiero hacer con esto, espero utilizar estos valores con frecuencia a lo largo de mi código. Por ejemplo, quiero poder hacer cosas como:

public void DoSomething(StatusCode currentStatus) { 
    if(currentStatus == StatusCode.Failure) { 
     throw new SomeException(); 
    } 

    switch(currentStatus) { 
     case StatusCode.Unknown: 
      // do something 
      break; 
    } 
} 

Y así sucesivamente. En particular, quiero evitar cosas como:

public void DoSomething(char currentStatus) { 
    if(currentStatus == 'F') { 
     // do something 
    } 
} 

Dado que en este caso estoy usando lo que equivale a "números mágicos" por todo el lugar. En particular, esto haría que la migración a algún otro sistema de bandera estatal sea prácticamente imposible. ¿Tiene sentido?

+0

Véase también http://stackoverflow.com/questions/1167927/syncing-referential-integrity-tables-and-enums y http://stackoverflow.com/questions/1015058/enum-storage-in- database-field, y en general, http://stackoverflow.com/search?q=enum%20database&tab=newest –

Respuesta

5

¿Quizás un objeto "constante"?

public sealed class StatusCode { 
    private char value; 

    public static readonly StatusCode Unknown = new StatusCode('U'); 
    public static readonly StatusCode Failure = new StatusCode('F'); 

    private StatusCode(char v) { 
     value = v; 
    } 

    public override string ToString() { 
     return value.ToString(); 
    } 

} 

Entonces, adelante en el código, se podría utilizar como una enumeración: StatusCode.Unknown. También podría proporcionar un método interno para 'analizar' un valor recibido en un objeto de Código de estado.

+2

también debe proporcionar igualdad implícita para proporcionar una comparación correcta para ciertos valores ... –

+0

¡Así es! : D – Fernando

+0

OK, creo que esta es la ruta que voy a seguir. Desafortunadamente, las declaraciones de casos todavía no funcionan como me gustaría, pero al menos todo lo demás lo hace. (¡Como el antiguo modelo enum de Java!) –

0

Si estás en .NET 2.0 y superior, se podría implementar esta usando un diccionario genérico:

Dictionary<char,string> statusCode = new Dictionary<char,string>(); 
statusCode.Add('U', "Unknown"); 
statusCode.Add('F', "Failure"); 

o alternativamente:

Dictionary<char,StatusCode> statusCode = new Dictionary<char,StatusCode>(); 
statusCode.Add('U', StatusCode.Unknown); 
statusCode.Add('F', StatusCode.Failure); 

y se podía acceder a la representación de cadena para una código dado de este modo:

string value = statusCode['A']; 

o

StatusCode myCode = statusCode['A']; 

y así sucesivamente. Tendría que llenar ese diccionario a partir de los valores de la base de datos, o de algún tipo de archivo de configuración o algo así.

Marc

0

¿Funcionaría así para usted?

public Enum StatusCode : int{ 
    [StringValue("U")] 
    Unknown =0, 
    [StringValue["F"] 
    Failuer=1 
} 
+0

es su parte de StringValue Attribute del framework .NET? Una búsqueda rápida en Google muestra un par de clases con ese nombre, pero nada en MSDN – STW

+0

http://weblogs.asp.net/stefansedich/archive/2008/03/12/enum-with-string-values-in-c.aspx tiene un ejemplo completo de implementación. Sin – JasonTrue

1

Saltar a editar ¿Has probado esto (que no funciona como después de estas comprobaciones comentado):

public enum StatusCode : char 
{ 
    Failure = 'F', 
    Unknown = 'U', 
    ... 
} 

EDITAR - solución correcta
o esto (tal vez siquiera trató con una struct):

public sealed class StatusCode 
{ 
    public static readonly char Failure = 'F'; 
    public static readonly char Unknown = 'U'; 
    ... 
    public char Value { get; set; } 
} 

su código que ya ha proporcionado sería wor k como esto:

public void DoSomething(StatusCode currentStatus) { 
    if(currentStatus.Value == StatusCode.Failure) { 
     throw new SomeException(); 
    } 

    switch(currentStatus.Value) { 
     case StatusCode.Unknown: 
      // do something 
      break; 
    } 
} 

Si no te gusta usar Value propiedad siempre se puede poner en práctica operador de igualdad implícita entre StatusCode y char tipos. En ese caso, su código no cambiaría un poco.

+0

buena: compilador da: error Tipo de bytes, sbyte, corta, ushort, int, uint largo, o ulong expecte –

+2

Hey ahora, no hay razón para traer malas palabras en esto. ;-) –

+0

^^ ¡Casi me lo perdí! : D – Jagd

0

Si tiene una tabla llamada StatusCode que incluye una clave primaria entera, puede usarla como su identificador y también engancharla en su lógica. Y en ese caso, la enumeración sería lo mejor para usar. Aunque no estoy seguro si esto es factible para ti.

0

Una opción es la configuración de su enumeración con nombres idénticos a los valores en su base de datos, tales como:

enum StatusCode 
{ 
    /// <summary>Unknown</summary> 
    U = 0, 
    /// <summary>Failure</summary> 
    F, 
    /// <summary>Etc</summary> 
    E 
} 

continuación, utilizar un método estático para convertir los valores char a un valor enumerado

private StatusCode CharToEnum(string statusCodeChar) 
    { 
     foreach (FieldInfo fi in typeof(StatusCode).GetFields()) 
     { 
      if (fi.Name == statusCodeChar) return (StatusCode)fi.GetValue(null); 
     } 

     return StatusCode.U; 
    } 
0

Corto y dulce mi hombre .. Hace todo lo que necesita. No debería necesitar usar enum porque no lo necesita para asignar un valor interno a sus posibles estados, ya conoce los valores para sus estados.

public sealed class StatusCode 
{ 
    public const string Unknown= "U"; 
    public const string Failure= "F"; 
    public const string Success= "S"; 
} 
Cuestiones relacionadas