假设我有以下课程:
struct Vector
{
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
}
class Player
{
public string Name { get; set; }
public Vector Position { get; set; }
}
如何在实体框架(核心)中配置它,使其映射到 Name、PositionX、PositionY、PositionZ?
这是为了代码生成目的,所以我不希望用户必须在创建 POCO 时考虑到 EF(它也会发送到很多其他语言!)
目前(EF Core 3)不支持。然而,有一个关于它的 GitHub 问题,看起来 structs-as-owned-types 已被接受用于未来版本:
正在寻找同样的东西,并遇到了这个问题。我想发布我发现的内容:EF Core 团队建议将其作为 JSON 存储在数据库中并使用自定义值转换器:
modelBuilder.Entity<Order>()
.Property(e => e.Vector)
.HasConversion(
v => JsonSerializer.Serialize(v, null),
v => JsonSerializer.Deserialize<Vector>(v, null));
但并不理想。
这可以通过 ef-core 8 实现。这是 Whatsnew 页面的链接,您可以在其中找到该功能的完整说明以及选择正确类型的一些指导。这似乎是非常重要的一点。查看
records
,尤其是 record struct
或不可变的 readonly record struct
,以确保选择最佳实现。
如果您的类型是类,您可以为数据库配置对其进行注释:
[ComplexType]
public class SomeClass
{
...
}
但是这不适用于记录、结构等。对于这些类型,您必须使用 FluentApi:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Player>().ComplexProperty(e=>e.Position);
}
默认情况下,此实现会生成一个包含以下列的表
Player
:
Name | Position_X | Position_Y | Position_Z
如果你想配置 Vector 的列,你可以这样做:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Player>().ComplexProperty(e=>e.Position, b=>
{
b.Property(p=>p.X).HasColumnType("whatever");
....
});
}
对于 Entity Framework Core,您所描述的称为 拥有的实体
配置类似于:
modelBuilder.Entity<Player>()
.OwnsOne(p => p.Position);