在实体框架4中遇到了enum
属性支持的缺失,我发现这篇文章描述了一种解决方法:
如何在代码中而不是在设计器中表示数据库列到OrderStatusWrapper
(如文章中所述)的映射?
更新
根据提供的答案,我没有意识到我需要用OrderStatus
类型替换OrderStatusWrapper
枚举,即
而不是:
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<Order> Orders { get; set; }
// }
using(OrderContext ctx = new OrderContext())
{
Order order = new Order { Status = OrderStatus.Created; }
ctx.Orders.Add(order);
ctx.SaveChanges();
}
引发以下异常(为简洁而修剪):
System.Data.SqlClient.SqlException Message=Invalid column name 'Value'.
数据库列名为Status
。我尝试使用:
Status
属性
[Column("Status")]
然后
[Column("Status"), TypeName("OrderStatus")]
和
[Column("Status"), TypeName("OrderStatusWrapper")]
但这并不能解决这个异常。
我还尝试删除Column
属性并执行此操作:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.Property(p => p.OrderStatus)
.HasColumnName("OrderStatus");
}
但是我得到以下编译错误:
错误1类型'ConsoleApplication1.OrderStatusWrapper'必须是非可空值类型,才能在泛型类型或方法'System.Data.Entity.ModelConfiguration.Configuration中将其用作参数'T'。 Types.StructuralTypeConfiguration.Property(System.Linq.Expressions.Expression&gt;)'[snipped path]
答案 0 :(得分:3)
在上下文文件中写下:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ComplexType<OrderStatusWrapper>();
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。
答案 1 :(得分:3)
以下代码是Code First CTP5中映射的外观。在这种情况下,Code First会自动将OrderStatusWrapper
识别为复杂类型,因为基于 Reachability Convention 的复杂类型发现这一概念。您甚至不需要使用ComplexTypeAttribute
或ComplexType<T>()
流畅的API将OrderStatusWrapper显式注册为复杂类型。
欲了解更多信息,请查看这篇文章:
的 Entity Association Mapping with Code First CTP5: Complex Types 强>
由于CTP5中存在错误,如果您希望为复杂类型属性设置自定义列名称(例如[订单]。[状态]为DB中的OrderStatusWrapper.Value),则必须使用{显式标记它{1}}:
[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
}