在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( );

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

相关推荐
梦想平凡1 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
TianyaOAO2 小时前
mysql的事务控制和数据库的备份和恢复
数据库·mysql
Ewen Seong2 小时前
mysql系列5—Innodb的缓存
数据库·mysql·缓存
码农老起2 小时前
企业如何通过TDSQL实现高效数据库迁移与性能优化
数据库·性能优化
夏木~3 小时前
Oracle 中什么情况下 可以使用 EXISTS 替代 IN 提高查询效率
数据库·oracle
W21553 小时前
Liunx下MySQL:表的约束
数据库·mysql
黄名富3 小时前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
言、雲3 小时前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
一个程序员_zhangzhen4 小时前
sqlserver新建用户并分配对视图的只读权限
数据库·sqlserver
zfj3214 小时前
学技术学英文:代码中的锁:悲观锁和乐观锁
数据库·乐观锁··悲观锁·竞态条件