在 EF Core 中分解结构?

问题描述 投票:0回答:4

假设我有以下课程:

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(它也会发送到很多其他语言!)

c# entity-framework
4个回答
3
投票

目前(EF Core 3)不支持。然而,有一个关于它的 GitHub 问题,看起来 structs-as-owned-types 已被接受用于未来版本:

https://github.com/dotnet/efcore/issues/9906


1
投票

正在寻找同样的东西,并遇到了这个问题。我想发布我发现的内容:EF Core 团队建议将其作为 JSON 存储在数据库中并使用自定义值转换器:

modelBuilder.Entity<Order>()
    .Property(e => e.Vector)
    .HasConversion(
        v => JsonSerializer.Serialize(v, null),
        v => JsonSerializer.Deserialize<Vector>(v, null));

但并不理想。


0
投票

这可以通过 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");
        ....
    });
}

-4
投票

对于 Entity Framework Core,您所描述的称为 拥有的实体

配置类似于:

modelBuilder.Entity<Player>()
    .OwnsOne(p => p.Position);
© www.soinside.com 2019 - 2024. All rights reserved.