如何使用代码优先CTP5将列映射到EF4中的复杂类型?

在entity framework4中遇到了缺少enum属性支持的问题,我发现这篇文章描述了一个解决方法:

Entity Framework 4.0 Beta 1 – POCO Enum支持?

如何在代码中而不是在设计器中表示数据库列到OrderStatusWrapper (如文章中所述)的映射?

更新:

根据提供的答案,我没有意识到我需要用OrderStatusWrapper类型替换OrderStatus枚举,即

代替:

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

我应该用:

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

这让我更进一步,但是在执行以下代码时:

 // OrderContext class defined elsewhere as: // public class OrderContext : DbContext // { // public DbSet Orders { get; set; } // } using(OrderContext ctx = new OrderContext()) { Order order = new Order { Status = OrderStatus.Created; } ctx.Orders.Add(order); ctx.SaveChanges(); } 

引发以下exception(为简洁起见,修剪):

 System.Data.SqlClient.SqlException
            消息=无效的列名称“值”。

数据库列名为Status 。 我尝试用以下内容装饰Status属性:

[Column("Status")]

然后

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

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

但这并不能解决这个exception。

我也尝试删除Column属性并执行此操作:

 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .Property(p => p.OrderStatus) .HasColumnName("OrderStatus"); } 

但是我得到以下编译错误:

错误1类型’ConsoleApplication1.OrderStatusWrapper’必须是非可空值类型,才能在generics类型或方法’System.Data.Entity.ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.Property中将其用作参数’T’( System.Linq.Expressions.Expression>)'[剪切路径]

在上下文文件中写这个:

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

它应该工作。

编辑:

 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 }); ...; } 

如果你按照那个例子展示了那个小代码,我展示了上面的内容(直到编辑:)应该按预期工作。

编辑nr2:如果我们的包装器看起来像这样:

 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; } } 

数据库采用属性Value的名称,因此如果将该属性名称更改为Status,则数据库中的列将更改为Status。

以下代码是Code First CTP5中映射的外观。 在这种情况下,Code First将自动将OrderStatusWrapper识别为复杂类型,因为称为复杂类型发现的概念基于可达性约定 。 您甚至不需要使用ComplexTypeAttributeComplexType()流畅的API来显式注册OrderStatusWrapper作为复杂类型。

欲了解更多信息,请看看这篇文章:
使用Code First CTP5进行实体关联映射:复杂类型

更新:

由于CTP5中存在错误,如果要为复杂类型属性设置自定义列名称(例如,[订单]。[DB中的OrderStatusWrapper.Value的[Status]),则必须使用[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 } 

由于您正在使用现有数据库,因此您也可以选择关闭数据库中的元数据表:

 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Conventions .Remove(); }