在EFCore中,我何时需要在值对象中添加[Owned]特性?

报错内容:System.InvalidOperationException:"The entity type 'xxx' cannot be configured as owned because it has already been configured as a non-owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'.

原因:我在实体中添加了一个值对象。值对象如下:

有一个枚举类型的属性Weekday,由于显式得未配置 [Owned] 特性 导致报错

cs 复制代码
    public class WeeklyLoopTimeStamp:ValueObject
    {
        // 日期
        public DayOfWeek Weekday
        {
            get; set;
        }
        // 时间
        public DateTime TimePoint
        {
            get; set;
        }

        protected override IEnumerable<object> GetAtomicValues()
        {
            yield return Weekday;
            yield return TimePoint;
        }
    }

在EF Core中,当你想要将属性标记为值对象,并且希望EF Core将其配置为复合类型(Complex Type)时,你需要在值对象的属性上添加[Owned]特性。

添加[Owned]特性的好处是,EF Core会自动处理该属性与其所属实体之间的映射和关系。它简化了代码,并减少了手动配置的工作量。

然而,并非所有情况下都需要添加[Owned]特性。以下是一些情况说明:

  1. 当属性的数据类型本身是一个简单的值类型(如string、int、DateTime等)时,EF Core会自动将其视为复合类型的一部分,无需添加[Owned]特性。

  2. 当属性的数据类型是自定义的类或结构体,并且你希望将其视为独立的实体类型(拥有自己的唯一标识符),而不是复合类型时,你不需要添加[Owned]特性。

  3. 当属性是一个集合类型(如List、ICollection等)时,EF Core会自动将其配置为导航属性,不需要添加[Owned]特性。

所以,只有当你确实希望将属性配置为值对象并作为复合类型存储在同一个数据库表中时,才需要在值对象的属性上添加[Owned]特性。

如果没有添加[Owned]特性而不报错,很可能是由于EF Core的默认行为能够正确地推断出属性应该被视为复合类型。然而,为了明确你的意图并提高代码的清晰度,建议在值对象的属性上显式添加[Owned]特性

拓展问题:

1. 值对象在数据表中以何种结构被存储?

在数据库中,如果一个实体拥有一个值对象属性,通常会将该值对象的属性作为实体表中的进行存储。

简单理解为:值对象的属性会被提取到实体属性中,从而成为单独的一列

对于你提到的WxTemplateForPlanOrderEntity实体,如果WeeklyLoopTimeStamp是一个值对象属性,那么通常会根据数据库的设计,创建一个包含WeeklyLoopTimeStamp属性的列。

具体地,可以根据你所使用的数据库类型和ORM框架的要求,将WeeklyLoopTimeStamp属性的值序列化为适当的数据类型(例如字符串、JSON等),并将其存储在数据库表的相应列中。

例如,在关系型数据库中,你可以将WeeklyLoopTimeStamp属性的值以JSON格式序列化,并将其存储为varchar或json类型的列。在NoSQL数据库中,可能会选择直接将WeeklyLoopTimeStamp属性的值存储为文档或字段的形式。

需要注意的是,数据库中的列与实体的属性之间需要进行映射关系的配置。这通常由ORM框架负责处理,通过特定的注解、配置文件或代码来定义实体属性与数据库列之间的映射关系。

综上所述,数据库的存储方式取决于数据库类型、ORM框架和相关配置,但一般来说,值对象属性会被作为实体表中的单独列进行存储。

2. 如果实体下的值对象是一对多关系?数据表中会如何存储?

例子:

cs 复制代码
    /// <summary>
    /// 发送数据时机 按周循环
    /// </summary>
    public List<WeeklyLoopTimeStamp> WeeklyLoopTimeStamp
    {
        get;
        set;
    }

那么需要根据ORM来配置,一般会创建一张另外的关联表。外键与实体相关联。

cs 复制代码
builder.OwnsMany( );

具体传入的配置方法需要根据项目规范制定。

相关推荐
码云骑士7 小时前
Redis 入门实战:从 NoSQL 概念到安装与基础操作详解(一)
数据库·redis·缓存
YL200404267 小时前
MySQL-进阶篇-锁
数据库·mysql
爱喝水的鱼丶8 小时前
SAP-ABAP:数据类型与数据对象(8篇) 第七篇:进阶优化篇——基于类型与对象特征的性能优化技巧
运维·数据库·学习·性能优化·sap·abap·开发交流
SelectDB技术团队8 小时前
PB 级自动驾驶数据秒级检索:Apache Doris 统一多模态数据平台实践
数据库·人工智能·自动驾驶·apache doris·selectdb
爱编程的小新☆8 小时前
LangGraph4j工作流框架
前端·数据库·ai·langchain·langgraph4j
programhelp_8 小时前
Google 2026 New Grad SDE VO 三轮面试详解 | 含Behavioral、Coding、Design
java·服务器·数据库
czhc11400756638 小时前
数据库520 HALCONAN安装
数据库
阿坤带你走近大数据8 小时前
Oracle中的OGG介绍
数据库·oracle
Ether IC Verifier8 小时前
TCP/IP协议握手原理详解——结合以太网连接过程
服务器·网络·数据库·网络协议·tcp/ip
宋浮檀s9 小时前
SQL注入基础+DVWA搭建
数据库·sql·安全·网络安全