如何使用代码优先 CTP5 将列映射到 EF4 中的复杂类型?
在遇到 Entity Framework 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")]< /code>
和
[Column("Status"), TypeName("OrderStatusWrapper")]
但这并不能解决此异常。
我还尝试删除 Column
属性并执行此操作:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.Property(p => p.OrderStatus)
.HasColumnName("OrderStatus");
}
但出现以下编译错误:
错误 1 类型“ConsoleApplication1.OrderStatusWrapper”必须是不可为 null 的值类型才能使用它作为泛型类型或方法“System.Data.Entity.ModelConfiguration.Configuration.Types.StructuralTypeConfiguration.Property(System.Linq.Expressions.Expression>)”中的参数“T”[截取路径]
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]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在上下文文件中写下:
它应该可以工作。
编辑:
如果您按照该示例所示的操作以及我显示的那一小段代码(直到编辑:)应该按预期工作。
编辑编号2:
如果我们的包装器如下所示:
数据库采用属性 Value 的名称,因此如果将该属性名称更改为 Status,数据库中的列将更改为 Status。
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.
以下代码是 Code First CTP5 中映射的样子。在这种情况下,由于基于可达性约定的称为复杂类型发现的概念,Code First 会自动将
OrderStatusWrapper
识别为复杂类型。您甚至不需要使用ComplexTypeAttribute
或ComplexType()
Fluent API 将 OrderStatusWrapper 显式注册为复杂类型。欲了解更多信息,请查看这篇文章:
使用 Code First CTP5 进行实体关联映射:复杂类型
更新:
由于 CTP5 中的错误,如果您想为复杂类型使用自定义列名称属性(例如 DB 中的 OrderStatusWrapper.Value 的 [Orders].[Status]),那么您必须使用
[ComplexType]
显式标记它:由于您正在使用现有数据库,因此您可以选择切换也关闭数据库中的元数据表:
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: