Enums and database fields...

Posts   
 
    
Posts: 497
Joined: 08-Apr-2004
# Posted on: 06-Oct-2004 16:13:40   

Hi all,

I am working with a set of DB tables that have lots of 1-char flags in the tables. For example a table "Customer" could have a Type_Flag, that is either I/E/U (Internal, External, Unknown -- made it up!)

Anyhow, in my code I like to work with enums for readibility. So, rather than say: if (entity.Type_Flag == "I") ...

I would like to say: if (entity.Type_Flag == TypeFlag.Internal)

Is there a straight forward way I can do this? Do I need to add more complexity to TypeFlag and turn it into a class instead of an enum, so I can add an "== operator"?

Ta!

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 06-Oct-2004 16:25:59   

Hi Matt

We use enums that resemble field values in a lookup table - that is why i wrote the enum task performer but it does not work with chars cry . _(Thanks to M$ who decided that a char is not a ordinal value rage - But funny enough - you can create a switch that works with strings??? frowning confused ) _

For Example - we use the enums with simple factories. wink

public  static TempPayment  CreateTempPaymentWithEnum (int operatorID, PaymentType TempPaymentType)
        {
            switch (TempPaymentType)
            {
                case PaymentType.CreditCard:
                    return CreateTempPaymentWithType(operatorID, typeof(CreditCardPayment));
                    
                case PaymentType.Cheque :
                    return CreateTempPaymentWithType(operatorID, typeof(Cheque));
                    
                case PaymentType.PostalOrder:
                    return CreateTempPaymentWithType(operatorID, typeof(PostalOrder));
                    
                case PaymentType.DebitChequeAccount :
                    return CreateTempPaymentWithType(operatorID, typeof(AccountPayment));

                default:
                    return null;
                    
            }
Posts: 497
Joined: 08-Apr-2004
# Posted on: 06-Oct-2004 17:15:48   

Thanks Wayne. Thats quite a nice example method you posted!

I was kinda hoping there would be a really easy way, my dream implemetation would have been:

public enum Type {
Internal = "I",
External = "E",
Unknown = "U"
}

ahh welll.....maybe in vs 2005 wink

jtgooding
User
Posts: 126
Joined: 26-Apr-2004
# Posted on: 06-Oct-2004 21:59:39   

Here is how I implement string enums, this might help you out =)

This version dynamically assigns enum values based on order like a real enum, this can also be tweaked to do static ones obviously.

    sealed class MyFakeEnum
    {
        private string name;
        private static int nextOrdinal = 1;
        private int ordinal = nextOrdinal++;

        private MyFakeEnum(String name)
        {
            this.name= name;
        }
        public override String ToString()
        {
            return name;
        }
        public int ToOrdinal()
        {
            return ordinal;
        }
        public static MyFakeEnum Internal = new MyFakeEnum("I"); // 1
        public static MyFakeEnum External = new MyFakeEnum("E"); // 2
        public static MyFakeEnum Unknown = new MyFakeEnum("U"); // 3
    }

John Gooding

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 07-Oct-2004 09:50:03   

I do have enums that does not correspond to the char values in the DB Tables.

    public enum ContractType : int
    {
        New,
        Renewal,
        Payment,
        Edit,
        View
    }

I use a static method in the BL Class where i am going to use this "Enum" to convert the char to a real enum.

        public static ContractType ConvertToContractType(string Contractype)
        {
            if (Contractype == "N") 
            {
                return ContractType.New; 
            }

            if (Contractype == "P") 
            {
                return ContractType.Payment;
            }

            if (Contractype == "R") 
            {
                return ContractType.Renewal;
            }

            if (Contractype == "E") 
            {
                return ContractType.Edit;
            }

            if (Contractype == "V") 
            {
                return ContractType.View;
            }

            throw new InvalidContractTypeException("ContarctType '" + Contractype + "' is not valid");
        }
wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 07-Oct-2004 09:53:13   

MattWoberts wrote:

Thanks Wayne. Thats quite a nice example method you posted!

Thanks, I love simple factories it really simplifies your code. I decided that i will post the full simple factory here for you


using System;
using BL.Magnet.CircData.Net.Payment; 

namespace BL.Magnet.CircData.Net.TempPayment
{
    /// <summary>
    /// Summary description for TempPaymentFactory.
    /// </summary>
    public sealed class TempPaymentFactory
    {
        public  static TempPayment  CreateTempPaymentWithEnum (int operatorID, PaymentType TempPaymentType)
        {
            switch (TempPaymentType)
            {
                case PaymentType.CreditCard:
                    return CreateTempPaymentWithType(operatorID, typeof(CreditCardPayment));
                    
                case PaymentType.Cheque :
                    return CreateTempPaymentWithType(operatorID, typeof(Cheque));
                    
                case PaymentType.PostalOrder:
                    return CreateTempPaymentWithType(operatorID, typeof(PostalOrder));
                    
                case PaymentType.DebitChequeAccount :
                    return CreateTempPaymentWithType(operatorID, typeof(AccountPayment));

                default:
                    return null;
                    
            }
        }

        public  static TempPayment  CreateTempPaymentWithEnumAndFill (int operatorID, PaymentType TempPaymentType, int FakeKey)
        {
            TempPayment Result = CreateTempPaymentWithEnum(operatorID, TempPaymentType);
            Result.Load(FakeKey);
            return Result;
        }

        public  static TempPayment CreateTempPaymentWithType (int operatorID,Type TempPaymentType)
        {
            object[] args = new object[1];
            args[0] = operatorID;
            return (TempPayment)Activator.CreateInstance(TempPaymentType,args);
        }
        
    }
}
Posts: 497
Joined: 08-Apr-2004
# Posted on: 19-Jan-2005 13:50:28   

Hi there.

I am using "string enums" loosely based on this example jt posted:


   sealed class MyFakeEnum
    {
        private string name;
        private static int nextOrdinal = 1;
        private int ordinal = nextOrdinal++;

        private MyFakeEnum(String name)
        {
            this.name= name;
        }
        public override String ToString()
        {
            return name;
        }
        public int ToOrdinal()
        {
            return ordinal;
        }
        public static MyFakeEnum Internal = new MyFakeEnum("I"); // 1
        public static MyFakeEnum External = new MyFakeEnum("E"); // 2
        public static MyFakeEnum Unknown = new MyFakeEnum("U"); // 3
    }

Now, i want to use my string enum in a switch statement, but I can't suss out what to do to get this to work:

// mattEnum is my enumerator, I will add an implicit operator to remove the need for
// excessive ToString calls ;)
switch (mattEnum)
{
case MyFakeEnum.Internal.ToString():
// Do something
break;
...
}

The problem is that this erorrs because c# wants a constant, and it considers my Internal.ToString method to be variable, quite rightly.. Anyone know what I should do?

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 19-Jan-2005 14:17:42   

That is the problem with .NET - No enum support for char. rage

Try casting it to enum - might work - if it doesn't then the only thing that i can suggest is an IF statement or a rework of your Enum example to a simmular method as i did it higher up in this thread - That will atleast give you a real enum to work with.

Posts: 497
Joined: 08-Apr-2004
# Posted on: 19-Jan-2005 17:16:55   

Thanks Wayne. I was hoping that with some more code in my class I could get round this, but it looks like I've been beaten on this one - so I'll have to use a workaround as you suggest...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 19-Jan-2005 18:00:26   

WHy not use a struct with string constants? Then you can still do: switch(myVal) { case TheStruct.Option1: break; ....

Frans Bouma | Lead developer LLBLGen Pro
Posts: 497
Joined: 08-Apr-2004
# Posted on: 20-Jan-2005 11:53:11   

Why is it that the easiest, most obvious solution was sitting there staring at me all along, while I attempted to write all sorts of silly code..... probably because I was too busy writing code to stop and think about what I wanted!

The solution:

public struct MattEnum
{
    private string value;
    
    public static implicit operator string (MattEnum val)
    {
        return val.value;
    }
    
    public void SetFromString(string val)
    {
        this.value = val;
    }

    public const string Normal = "N";
    public const string Incomplete = "I";
    public const string Missing = "M";
}

simple_smile