如何使用代码第一个CTP5将列映射到EF4中的复杂类型? [英] How do I map a column to a complex type in EF4 using code first CTP5?

查看:191
本文介绍了如何使用代码第一个CTP5将列映射到EF4中的复杂类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

碰到实体框架4中缺少枚举属性支持我发现这篇文章描述了一个解决方法:


实体框架4.0 Beta 1 - POCO枚举支持?


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



更新: / p>

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



而不是:

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

我应该使用:

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

这让我进一步,但是执行以下代码时: / p>

  //在其他地方定义的OrderContext类:
// public class OrderContext:DbContext
// {
// public DbSet< Order>订单{get;组;
//}
使用(OrderContext ctx = new OrderContext())
{
订单=新订单{Status = OrderStatus.Created; }
ctx.Orders.Add(order);
ctx.SaveChanges();
}

出现以下异常(为简洁起见):

 
System.Data.SqlClient.SqlException
Message =无效的列名称值。

数据库列命名为状态。我尝试用以下方式装饰状态属性:



[Column(Status)]



然后



[列(状态 ),TypeName(OrderStatus)]





[Column(Status),TypeName(OrderStatusWrapper)]



但是这并不能解决这个异常。 / p>

我还尝试删除属性,然后执行此操作:





modelBuilder.Entity< Order>()
.Property(p => p。 OrderStatus)
.HasColumnName(OrderStatus);
}

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



错误1类型ConsoleApplication1.OrderStatusWrapper必须是不可为空的值类型,以便在通用类型或方法System.Data.Entity中将其用作参数T。 ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.Property(System.Linq.Expressions.Expression>)'[snipped path]

解决方案

以下代码是Code First CTP5中的映射方式。在这种情况下,由于名称为复杂类型发现的概念,Code First将自动将 OrderStatusWrapper 识别为复杂类型,该概念基于可达性公约。您甚至不需要使用 ComplexTypeAttribute ComplexType< T>()流畅的API来显式地将OrderStatusWrapper注册为一个复杂的类型。



有关更多信息,请查看此文章:


实体协会使用代码第一个CTP5映射:复杂类型



更新:



由于CTP5中的错误,如果要为复合类型属性(例如DB中的OrderStatusWrapper.Value的[Orders]] [Status]设置自定义列名称,则必须使用 [ComplexType]

  public class Order 
{
public int OrderId {get;组; }
public DateTime CreatedOn {get;组; }
public OrderStatusWrapper Status {get;组; }
}

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

由于您正在使用现有数据库,您还可以选择在数据库中关闭元数据表: / p>

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


Having bumped into the of the lack of enum property support in Entity Framework 4 I discovered this article which describes a workaround:

Entity Framework 4.0 Beta 1 – POCO Enum support?

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 use ComplexTypeAttribute or the ComplexType<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]:

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 optionally switch off metadata table in database as well:

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

这篇关于如何使用代码第一个CTP5将列映射到EF4中的复杂类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆