ef core 配置的值对象必须初始化问题
在DDD里面 值对象是将一个值 用对象的方式进行表述,来表达一个具体的固定不变的概念。ef core 是 owned实现值对象。
pubic class Student : Entity<int> { public string Name { get; private set; } public ModifyUser ModifyUser { get; private set; } public Student(string name, ModifyUser modifyUser) { this.Name = name; this.ModifyUser = modifyUser; } } // 不建议用特性指定,这里只是为了演示 [Owned] public class ModifyUser : ValueObject { public string Name { get; private set; } public string Tel { get; private set; } public ModifyUser(string name, string tel ) { this.Name = name; this.Tel = tel; } protected override IEnumerable<object> GetAtomicValues() { yield return Name + Tel; } }
这里好像没什么问题,但是在业务里当创建Student时我好像不应该传入修改者的值对象,我们来修改下Studnet的代码:
pubic class Student : Entity<int> { public string Name { get; private set; } public ModifyUser ModifyUser { get; private set; } private Student(string name) { this.Name = name; } private Student(string name, ModifyUser modifyUser) { this.Name = name;
this.ModifyUser = modifyUser; } // 当执行新增时这里运行时会报错 public static Student CreateFactory(string name) { return new Student(name); } public static Student UpdateFactory(string name, ModifyUser modifyUser) { return new Student(name, modifyUser); } }
这里会报错的原因是 在逻辑中我们是正确的,新增时我们不应该有修改者的信息,但是在实现时我们没有考虑到技术上的问题,创建时值对象为null,
它是一个整体,不能为null 这个修改者可以为null,应该体现在这一句
yield return Name + Tel; 这代表值对象的整体的唯一标识
, 我们可以在CreateFactory 给 默认ModifyUser 无参构造函数 但是这样ModifyUser 就暴露出了一个无参构造函数,别人可能不太理解是什么意思,我们的解决办法是
pubic class Student : Entity<int> { public string Name { get; private set; } public ModifyUser ModifyUser { get; private set; } private Student(string name) { this.ModifyUser = ModifyUser.Empty; this.Name = name; } private Student(string name, ModifyUser modifyUser) { this.Name = name; this.ModifyUser = modifyUser; } public static Student CreateFactory(string name) { return new Student(name); } public static Student UpdateFactory(string name, ModifyUser modifyUser) { return new Student(name, modifyUser); } } // 不建议用特性指定,这里只是为了演示 [Owned] public class ModifyUser : ValueObject { public static readonly ModifyUser Empty = new ModifyUser(); public string Name { get; private set; } public string Tel { get; private set; } private ModifyUser() { } public ModifyUser(string name, string tel ) { this.Name = name; this.Tel = tel; } protected override IEnumerable<object> GetAtomicValues() { yield return Name + Tel; } }
这样虽然可以,但总感觉还是有问题!期待大佬们帮忙解惑!
补充:官方介绍
限制
其中一些限制对于拥有的实体类型的工作方式很重要,但其他一些限制是我们可以在未来版本中删除的限制:
按设计限制
- 不能
DbSet<T>
为拥有的类型创建 - 不能
Entity<T>()
对拥有的类型调用ModelBuilder
当前缺陷
- 拥有的实体类型不能具有继承层次结构
- 引用导航到拥有的实体类型不能为 null,除非它们显式映射到与所有者不同的表
- 拥有的实体类型的实例不能由多个所有者共享(这是一个已知的值对象方案,不能使用拥有的实体类型来实现)