How to map columns to complex type in EF4 using CTP5 code?

When faced with a lack of support for enum properties in Entity Framework 4, I found this article that describes a workaround:

Entity Framework 4.0 Beta 1 - POCO Enum Support?

How to express the mapping of a database column to OrderStatusWrapper (as described in the article) in the code, and not in the designer?

Update:

Based on the answers I did not understand, I need to replace the enum OrderStatus type OrderStatusWrapper , i.e.

Instead:

 public class Order { public OrderStatus Status { get; set; } } 

I have to use:

 public class Order { public OrderStatusWrapper Status { get; set; } } 

This is a bit more to me, but after 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 (abbreviated for brevity):

  System.Data.SqlClient.SqlException
             Message = Invalid column name 'Value'.

The database column is called Status . I tried decorating the Status property:

[Column("Status")]

then

[Column("Status"), TypeName("OrderStatus")]

and

[Column("Status"), TypeName("OrderStatusWrapper")]

But this does not eliminate 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 compilation error:

Error 1 The type "ConsoleApplication1.OrderStatusWrapper" must be an unimaginable value type in order to use it as the "T" parameter in the general type or method "System.Data.Entity.ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.Property (System.Linq.Expressions. Expression>) '[disabled path]

+4
source share
2 answers

in the context file write this:

  protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ComplexType<OrderStatusWrapper>(); base.OnModelCreating(modelBuilder); } 

he should work.

EDIT:

 public class Order { public... ... public OrderStatusWrapper OrderStatus { get; set; } } public ActionResult Index() { var result = _context.Orders.Where(o => o.OrderStatus == OrderStatus.ReadyForShipping); _context.Orders.Add(new Order{ ..., OrderStatus = OrderStatus.Shipped }); ...; } 

if you did this, as this example shows along with this small snippet of code, I showed above (until EDIT :) works properly.

EDIT nr2: If our cover looks like this:

 public class OrderStatusWrapper { private OrderStatus _status; public int Value { get { return (int)_status; } set { _status = (OrderStatus)value; } } public OrderStatus EnumValue { get { return _status; } set { _status = value; } } public static implicit operator OrderStatusWrapper(OrderStatus status) { return new OrderStatusWrapper { EnumValue = status }; } public static implicit operator OrderStatus(OrderStatusWrapper statusWrapper) { if (statusWrapper == null) return OrderStatus.OrderCreated; else return statusWrapper.EnumValue; } } 

The database uses the property name Value, so if you change this property name to Status, the column in the database changes to Status.

+3
source

The following code is how the mappings are displayed in Code First CTP5. In this case, Code First automatically recognizes OrderStatusWrapper as a complex type due to a concept called Complex Type Discovery, which operates on the basis of the Achievement Convention. You do not even need to use ComplexTypeAttribute or ComplexType<T>() free API to explicitly register OrderStatusWrapper as a complex type.

For more information, please take a look at this post:
Mapping Entities with the First CTP5 Code: Complex Types

Update:

Due to an error in CTP5, if you want to have your own column name for your complex type properties (for example, [Orders]. [Status] for OrderStatusWrapper.Value in the database), then you should explicitly mark it with [ComplexType] :

 public class Order { public int OrderId { get; set; } public DateTime CreatedOn { get; set; } public OrderStatusWrapper Status { get; set; } } [ComplexType] public class OrderStatusWrapper { private OrderStatus _status; [Column(Name="Status")] public int Value { get { return (int)_status; } set { _status = (OrderStatus)value; } } public OrderStatus EnumValue { get { return _status; } set { _status = value; } } } public enum OrderStatus { OrderCreated, OrderPayed, OrderShipped } 

Since you are working with an existing database, you can also disable the metadata table in the database:

 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Conventions .Remove<System.Data.Entity.Database.IncludeMetadataConvention>(); } 
+3
source

Source: https://habr.com/ru/post/1332685/


All Articles