ABP/DDD:将充血模型映射到EF Core

178 阅读1分钟

学习这个东西是这么一回事,打工这么久,有些时候是在把别人做过的东西按自己想法实现一遍。之前做上传三方报告的需求时候,其实别人已经做过上传诊断报告的需求了。

虽然两者实现的功能一样,但是代码设计上的是被秒成渣。自己做就是直接干,贫血模型一干到底,业务给domain,甚至全给application service。别人做就是充血模型,优雅。

前置笔记:领域驱动设计DDD:贫血模型和充血模型(比较重要)_董厂长的博客-CSDN博客

看注释!这边实现一个具有各种刁钻需求的充血模型:

public record User
{
	public int Id { get; init; }//特征一:只能初始化赋值
	public DateTime CreatedDateTime { get; init; }//特征一
	public string UserName { get; private set; }//特征一:只能在内部方法中改变
	public int Credit { get; private set; }
	private string? passwordHash;//特征三:不属于 属性 的 成员变量 映射为数据列
	private string? remark;
	public string? Remark //特征四:只读属性
	{
		get { return remark; } 
	}
 
	public string? Tag { get; set; }//特征五:不想映射到数据库
 
	private User()//特征二:给EF Core从数据库加载数据 然后生成user对象返回用的!
	{
 
	}
 
    public User(string yhm)//特征二:给普通用户创建对象用的
	    {
		    this.UserName = yhm;
		    this.CreatedDateTime = DateTime.Now;
		    this.Credit = 10;
	    }
 
	public void ChangeUserName(string newValue)
	{
		this.UserName = newValue;
	}
 
	public void ChangePassword(string newValue)
	{
		if (newValue.Length < 6)
		{
			throw new ArgumentException("密码太短");
		}
		this.passwordHash = HashHelper.Hash(newValue);
	}
}

重点复习一下特征2的原理

image.png

为了完成这些特征,需要这样写配置:

class UserConfig : IEntityTypeConfiguration<User>
{
	public void Configure(EntityTypeBuilder<User> builder)
	{
		builder.Property("passwordHash");//特征三
		builder.Property(u => u.Remark).HasField("remark");//特征四
		builder.Ignore(u => u.Tag);//特征五
	}
}

业务代码中:

User u1 = new User("FuckRJ");
u1.Tag = "MyTag";
u1.ChangePassword("123456");
ctx.Users.Add(u1);
ctx.SaveChanges();
 
User u1 = ctx.Users.First(u=>u.UserName=="FuckRJ");
Console.WriteLine(u1);