DDD/ABP/EF Core 实现值对象Value Object

有一说一DDD真tM抽象 :<, 看一遍真是看不懂。

简单理解值对象和实体的区别:

1. 实体具有唯一标识符,就是主键

2. 值对象无法单独存在,一定是依附于一个实体

举个栗子🌰, 地址的三个属性必须同时存在,缺少一个地址属性就没意义了。

class girlfriend
{string height;string weight;string location;
}class location
{string country;string city;string street;    
}

那么深入一些:值对象存在的意义 是 把领域知识 放到类的定义中。 

实现方式有2种 

1. “从属实体类型(owned entities)”:使用Fluent API中的OwnsOne等方法来配置。

2、在EF Core中,实体的属性可以定义为枚举类型,枚举类型的属性在数据库中默认是以整数类型来保存的。对于直接操作数据库的人员来讲,0、1、2这样的值没有“CNY”(人民币)、“USD”(美元)、“NZD”(新西兰元)等这样的字符串类型值可读性更强。EF Core中可以在Fluent API中用HasConversion()把枚举类型的值配置成保存为字符串。(看图二)

 方式2

 建议:值对象 定义为 record类型

​class ​是主要常用类型,属于引用类型,可以继承,可以多态,还可以定义抽象类。我们用的最多的。在进行两个类对象==操作时,默认比较的是对象的引用地址是否相等。


​struct ​是很早C语言就开始使用的数据结构,一般用于简单的数据,不能继承和多态,属于值类型,比较时,默认是进行类型相同并且里面的字段值相等。可以对每个成员变量进行比特位的控制,用于与C程序库中的数据类型进行互相通信时会使用,比如PInvoke时候就常用。


​​record ​​新增的类型,默认==操作是进行类型判断和成员值全部相等,也属于值类型。默认初始化之后,其成员数据是无法修改的。可以使用with快速方便的在复制一个副本时修改其中某些成员的值。但是其实现的复制是潜复制。
 

方式1

栗子:将坐标(经纬度)定义为值对象,设置构造函数,好处是在构造中就可以进行校验

这就是领域知识封装到一个类里面 !因为其他人是不知道经纬度的合法数值的!

record Geo{public double Longitude { get; init; }public double Latitude { get; init; }public Geo(double longitude, double latitude){if(longitude<-180||longitude>180)throw new ArgumentException("longitude invalid");if (latitude < -90 || latitude > 90)throw new ArgumentException("longitude invalid");this.Longitude = longitude;this.Latitude = latitude;}

注意,Location是一个从属实体属性 ,所以需要配置

看,配置完之后,数据库存储时候会将Location展开为2个列,并且附加到shop表内。

再次复习一下为什么两个 构造器 一个private 一个public!


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部