Having bumped into the of the lack of enum
property support in Entity Framework 4 I discovered this article which describes a workaround:
How do I express the mapping of a database column to the OrderStatusWrapper
(as described in the article) in code rather than in the designer?
Update:
Based on the answers provided, I hadn't realised that I needed to replace the OrderStatus
enum with the OrderStatusWrapper
type, i.e.
Instead of:
public class Order
{
public OrderStatus Status { get; set; }
}
I should be using:
public class Order
{
public OrderStatusWrapper Status { get; set; }
}
This gets me a bit further, however upon executing the following code:
// OrderContext class defined elsewhere as:
// public class OrderContext : DbContext
// {
// public DbSet<Order> Orders { get; set; }
// }
using(OrderContext ctx = new OrderContext())
{
Order order = new Order { Status = OrderStatus.Created; }
ctx.Orders.Add(order);
ctx.SaveChanges();
}
The following exception is raised (trimmed for brevity):
System.Data.SqlClient.SqlException Message=Invalid column name 'Value'.
The database column is named Status
. I tried decorating the Status
property with:
[Column("Status")]
then
[Column("Status"), TypeName("OrderStatus")]
and
[Column("Status"), TypeName("OrderStatusWrapper")]
But this doesn't resolve this exception.
I also tried removing the Column
attribute and doing this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.Property(p => p.OrderStatus)
.HasColumnName("OrderStatus");
}
But I get the following compile error:
Error 1 The type 'ConsoleApplication1.OrderStatusWrapper' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Data.Entity.ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.Property(System.Linq.Expressions.Expression>)' [snipped path]
The following code is how the mappings looks like in Code First CTP5. In this case Code First will automatically recognize
OrderStatusWrapper
as a complex type due to a concept called Complex Type Discovery that works based on the Reachability Convention. You don't even need to useComplexTypeAttribute
or theComplexType<T>()
fluent API to explicitly register OrderStatusWrapper as a complex type.For more info please take a look at this post:
Entity Association Mapping with Code First CTP5: Complex Types
Update:
Due to a bug in CTP5, if you want to have a custom column name for your complex type properties (e.g. [Orders].[Status] for OrderStatusWrapper.Value in DB), then you have to explicitly mark it with
[ComplexType]
:Since you are working with an existing database, you can optionally switch off metadata table in database as well:
in the context file write this:
it should work.
EDIT:
if you did as that example shows along with that small piece of code i showed the above (until EDIT:) should work as expected.
EDIT nr2: If our wrapper looks like this:
The database takes the name of the property Value, so if you change that property name to Status, the column in the database would change to Status.