2009-12-28 5 views
6

J'en fais un wiki communautaire, car j'apprécierais l'approche des gens et pas nécessairement une réponse.Enums ou Tables?

Je suis dans la situation où j'ai beaucoup de champs de données de type recherche, qui ne changent pas. Un exemple serait:

Salaire annuel
Option: 0 - 25K
Option: 25K - 100K
Option: 100K +

Je voudrais avoir ces options facilement disponibles par le biais d'une énumération, mais aimerait également les valeurs textuelles disponibles dans la base de données, car je ferai des rapports sur les valeurs textuelles et non sur un identifiant. En outre, comme ils sont statiques, je ne veux pas faire d'appels à la base de données.

Je songeais à reproduire cela dans une énumération et une table, mais j'aimerais entendre d'autres pensées.

Merci

Répondre

7

Je pense qu'une ENUM est une mauvaise idée. Juste donné le type de données que vous montrez, cela peut changer. Mieux vaut avoir une table de base de données avec les champs ID/Min/Max/Description que vous chargez lorsque votre application s'initialise.

+0

C'était un exemple, il ne changera pas. J'aime votre approche de toute façon, comment voulez-vous persister les données tout au long de l'application. Y aura-t-il des problèmes de performance étant donné que les données ne sont pas nécessaires pour 99% de l'application? –

+1

Si ces données sont rarement accessibles, vous pouvez simplement les conserver dans une classe statique qui est initialisée la première fois que vous demandez les données (initialisation paresseuse). Assurez-vous simplement que les verrous sont en place afin qu'un seul thread puisse accéder à ces données à la fois. Cela permettra d'éliminer les ralentissements de démarrage. Si vous ne voulez pas attendre la première fois que vous accédez aux données, vous pouvez également ajouter les données à une file d'attente de travail de priorité basse pour être chargées lorsqu'elles sont inactives pendant un moment ou deux (ou chargées immédiatement si nécessaire) – Eclipse

+2

Si cela ne change vraiment pas et que vous n'avez pas de base de données, vous pouvez simplement l'enregistrer dans votre fichier app.config dans une section personnalisée. –

1

J'utilise les deux. Dans Linq to SQL et EF, vous faites simplement de la propriété column un type enum. Dans d'autres cadres, vous pouvez généralement mapper la colonne à une propriété enum d'une manière ou d'une autre. Vous pouvez toujours avoir une table de clé primaire dans la base de données contenant des énumérations valides. Vous pouvez également le faire avec une contrainte CHECK dans la base de données, mais cela tend à lier vos données à votre application - quelqu'un qui regarde la base de données ne sait pas nécessairement ce que chaque valeur signifie. Donc je préfère la table hybride/enum.

0

Assurez-vous d'abord que ces données sont vraiment statiques. Si quelque chose change, vous devrez recompiler et redéployer.

Si les données sont vraiment statiques, je passerais à la route enum. Vous pouvez créer un YearlySalaryEnum contenant toutes les valeurs. Pour la représentation sous forme de chaîne, j'utiliserais un dictionnaire avec des valeurs de chaîne et le YearlySalaryEnum comme clé. Le dictionnaire peut être maintenu en tant qu'instance statique dans une classe statique. Utilisation serait le long des lignes de (C#):

string highSalary = StaticValues.Salaries[YearlySalaryEnum.High]; 
+0

Qu'en est-il des rapports SQL? Comment cela serait-il résolu en utilisant une approche enum seulement. –

+1

Initialiser le dictionnaire à partir de DB, assez facile. Si le type de données derrière l'énumération est un entier, le mappage vers une colonne db est simple. Comme l'a souligné Aaron, de nombreux ORM peuvent le faire dès la sortie de la boîte. –

-1

Utilisez les deux ENUM (pour le code) et DB texts- pour la présentation de l'interface graphique.

Donc, si vous avez toujours l'option 3 utiliser un ENUM LowSalary, MiddleSalary et HighSalary, stocker vos textes dans la base de données et de passer vos textes dans l'interface graphique correspondant à votre propriété valeur ENUM.

1

Utilisez les deux, Et vous devriez étudier le CodeDOM. En utilisant ceci, vous pouvez écrire des routines de génération de code qui permettent au processus de compilation de générer automatiquement un assembly ou une classe avec ces énumérations, en lisant la base de données. De cette façon vous pouvez laisser la base de données conduire, mais vous n'appelez pas à la base de données chaque fois que vous accédez à une instance de l'énumération ...

0

Puisque C# n'autorise pas les Enums avec des valeurs de chaîne, je suggère un struct avec des chaînes statiques.De cette façon, vous maintenez une certaine Intellisense, mais sans essayer de chausse une valeur Enum sur ce qu'est une valeur de chaîne dans la base de données.

L'autre solution que je proposerais: supprimer la logique qui dépend de ces valeurs et passer à la logique de table. (Par exemple, si chaque tarif a un taux de taxe différent, ajoutez un taux de taxe en tant que colonne dans la base de données plutôt qu'un cas {} dans le code.).

2

Une façon est d'écrire un formatter qui peut vous transformer ENUM en représentations de chaîne:

public class SalaryFormatter : IFormatProvider, ICustomFormatter 
{ 
    public object GetFormat(Type formatType) 
    { 
     return (formatType == typeof(ICustomFormatter)) ? new 
     SalaryFormatter() : null; 
    } 

    public string Format(string format, object o, IFormatProvider formatProvider) 
    { 
     if (o.GetType().Equals(typeof(Salary))) 
     { 
      return o.ToString(); 

      Salary salary = (Salary)o; 
      switch (salary) 
      { 
       case Salary.Low: 
        return "0 - 25K"; 
       case Salary.Mid: 
        return "25K - 100K"; 
       case Salary.High: 
        return "100K+"; 
       default: 
        return salary.ToString(); 
      } 
     } 

    return o.ToString(); 
    } 
} 

Vous utilisez le formatter comme tout autre formatter:

Console.WriteLine(String.Format(new SalaryFormatter(), "Salary: {0}", salary)); 

Le formatter peut être extented à l'appui différents formats grâce à des chaînes de formatage, plusieurs types, la localisation et ainsi de suite.

+0

Je pense qu'ils ne vont pas apprécier l'idée. Je ne sais pas pourquoi, mais avoir une table de base de données pour ces 3 variables est mieux vu par eux ... – serhio

1

Jetez un oeil à ma suggestion How to work with Enums in Entity Framework?

Essentiellement, j'utilise des valeurs par défaut des scripts SQL pour les données de consultation de base, avec les ID pour les références FK d'autres tables, puis-je utiliser un modèle simple T4 pour générer mes énumérations pour C#. De cette façon, la base de données est efficace, normalisée et correctement contrainte, et mes entités C# n'ont pas à gérer les identifiants (nombres magiques).

C'est simple, rapide, facile et fait le travail pour moi.

J'utilise EF4, mais vous n'avez pas besoin, pourrait utiliser cette approche avec la technologie que vous utilisez pour vos entités.

6

Pour les éléments statiques, j'utilise Enum avec l'attribut [Description()] pour chaque élément. Et modèle T4 REGÉNÈRE ENUM avec des descriptions sur la construction (ou chaque fois que vous voulez)

public enum EnumSalary 
    { 
     [Description("0 - 25K")] Low, 
     [Description("25K - 100K")] Mid, 
     [Description("100K+")] High 
    } 

et de l'utiliser comme

string str = EnumSalary.Mid.Description() 

post-scriptum a également créé l'extension pour System.Enum

public static string Description(this Enum value) { 
    FieldInfo fi = value.GetType().GetField(value.ToString()); 
    var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof(DescriptionAttribute), false); 
    return attributes.Length > 0 ? attributes[0].Description : value.ToString(); 
} 

et arrière pour créer ENUM par une description

public static TEnum ToDescriptionEnum<TEnum>(this string description) 
{ 
    Type enumType = typeof(TEnum); 
    foreach (string name in Enum.GetNames(enumType)) 
    { 
     var enValue = Enum.Parse(enumType, name); 
     if (Description((Enum)enValue).Equals(description)) { 
      return (TEnum) enValue; 
     } 
    } 
    throw new TargetException("The string is not a description or value of the specified enum."); 
}