27

I am using Entity Framework 5, DB first. I know how to define an enum on my model, and set the type of a field to that enum.

Now, I have a requirement to map a field MyField to an enum that is defined externally, i.e. not in the EF model (OtherNamespace.MyEnum). The designer does not allow me to set the type to anything outside the model. I tried editing the edmx file manually, but that causes an error:

Error 10016: Error resolving item 'MyField'. The exception message is: 'Unresolved reference 'OtherNamespace.MyEnum'.'.

OtherNamespace.MyEnum is referenced by my project.

How do you do it?

Shaul Behr
  • 36,951
  • 69
  • 249
  • 387

1 Answers1

53

This can be done, but it requires a little sacrifice on the database side. Entity Framework (5 onwards) supports mapping a field to an enumeration, but only for byte, sbyte, short, ushort, int, uint, long, or ulong types.

Assume that we have the following sample table:

CREATE TABLE [People](
    [id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [Name] [varchar](50) NOT NULL,
    [Title] [int] NOT NULL
)

Title has been declared as an integer. In a real database, this might be a foreign key over to a TitleTypes table.

Also, let's assume that the external enumeration that we are going to be tying into is defined as:

namespace Enumerations
{
    public enum TitleEnum
    {
        Mr,
        Mrs,
        Dr,
        None
    }
}

If we import the People table into an EDMX we can right click on the Title column and Convert to Enum

Convert To Enum

This will bring up a dialog box allowing us to specify a name for the enumeration in the EDMX ModelStore, define any values for the enumeration OR link to an external enumeration via Reference external type.

Give it a Type Name of TitleEnum, check Reference external type, and type Enumerations.TitleEnum in the provided field. Click OK and it will associate the column to the external enumeration.

Note:

  • While both are called TitleEnum, this is acting as a passthrough to the external Enumeration
  • The type of your column and the external enumeration MUST match

Linking the Enumeration

Now, when we create a new person we can utilize the enumeration and it will be translated into its Int representation.

Data.ScratchEntities context = new Data.ScratchEntities();
Data.Person person = new Data.Person();
person.Name = "Jane Smith";
//Note the use of the external enumeration here
person.Title = Enumerations.TitleEnum.Mrs;
context.People.Add(person);
context.SaveChanges();

Intellisense

David Silva-Barrera
  • 1,006
  • 8
  • 12
cbeckner
  • 1,808
  • 15
  • 17
  • 1
    Thanks for a beautifully documented answer. But it's not working for me. Everything is fine up to the last step - but I'm getting a compiler error: cannot convert source type `Enumerations.TitleEnum` to target type `MyNamespace.TitleEnum`. What am I doing wrong? Could it be because my base type is `byte` rather than `int`? – Shaul Behr Oct 07 '13 at 19:59
  • 1
    Yes. The type of the column and the base type for the enum will need to match so that it can do an implicit conversion from one to the other. – cbeckner Oct 08 '13 at 07:03
  • 1
    The column in the db is a tinyint, which maps to byte...? And if that were the case, an explicit cast should work - but it doesn't. – Shaul Behr Oct 08 '13 at 07:19
  • To my knowledge, when mapping enum to enum it is not possible to explicitly cast the type when setting the value. What DOES work in this situation however is to leave the EF type definition for that field as a `byte` and when you are setting the value from the enumerations cast the enum value to the appropriate type: `td.Title = (byte)Enumerations.TitleEnum.Mr;` – cbeckner Oct 08 '13 at 07:36
  • Still doesn't make sense. Your screen shot shows that Intellisense is automatically choosing `Enumerations.TitleEnum` to assign to a variable of type `MyNamespace.TitleEnum`. My compiler doesn't even accept it, much less Intellisense. If I look at the generated code, the `MyNamespace.TitleEnum` is just an empty enum type. Perhaps it's a problem with my code generation template? What does your generated code look like? – Shaul Behr Oct 08 '13 at 07:55
  • 1
    When you **Converted to Enum** in the EDMX, did you specify the external enumeration? Trying to replicate your errors, when I remove the reference, I get the exact error message you mention in the first comment above. You can edit the existing enum mapping via the Model Browser under Enum Types (sorry it took me an hour to get there, hadn't had coffee yet) – cbeckner Oct 08 '13 at 08:07
  • Yes, I did specify the external enum. It doesn't make any difference in the generated code – Shaul Behr Oct 08 '13 at 08:23
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/38767/discussion-between-cbeckner-and-shaul) – cbeckner Oct 08 '13 at 08:31
  • Ping - please check chat – Shaul Behr Oct 12 '13 at 17:27
  • Perfect - I didn't know about this so I just implemented a property that converted my int to an enum on the Get; and enum to int on the Set; which seemed to work...UNTIL I tried using a scaffolded Edit page. I could display the selected enum using the EnumDropDownListFor() method and my new property but it didn't work when you came to the save. This works perfectly. I guess the only downside is if I update the database table and have to update the edmx, but it should be relatively easy to redo the above step. (20 seconds work). – Percy Mar 29 '15 at 12:26
  • For anyone who wants to use the same enum for properties in multiple classes (e.g. a culture type), you don't need to do the above everytime - infact you can't! You just need to click on the property on the edmx designer and select the type from the dropdown list in the properties window. This wasn't obvious to me so I thought I'd comment and help anyone else who wants to do this. – Percy Mar 29 '15 at 16:42
  • make sure you declare the type of the enum, for example: public enum LookupEnum : int { Value1 = 1, Value2 = 2 } – MaurGi Jul 16 '15 at 22:28
  • What font is that in your IDE? – test Jun 09 '16 at 22:49
  • A tip for anyone who gets the namespace or type name wrong on their external reference: you can correct it via the "Model Browser" (right click on EDMX diagram background to get this window) by expanding "Enum Types", single clicking on the EDMX copy of the enum, then on your "Properties" window, modifying "External Type". Save your EDMX after and it should re-generate the type reference on any properties using it in the EDMX. – Matt Arnold Nov 04 '19 at 16:03