DDD之EFCore实现值对象

DDD之EFCore实现值对象

Region


public record Region
{
    public long Id { get; init; }
    public MultilingualString Name { get; init; }
    public Area Area { get; init; }
    public RegionLevel Level { get; private set; }
    public long? Population { get; private set; } //人口
    public Geo Location { get; init; }
    private Region() { }
    public Region(MultilingualString name, Area area, Geo location,
        RegionLevel level)
    {
        this.Name = name;
        this.Area = area;
        this.Location = location;
        this.Level = level;
    }

    public void ChangePopulation(long value)
    {
        this.Population = value;
    }
    public void ChangeLevel(RegionLevel value)
    {
        this.Level = value;
    }

}

//多语言
public record MultilingualString(string Chinese, string? English);

//区域大小
public record Area(double Value, AreaType Unit);
public enum AreaType
{
    SquareKM,//平方米
    Hectare, //公顷
    CnMu     //
}

//城市级别
public enum RegionLevel
{
    Province,//省
    City,    //城市
    County,  //国家
    Town     //城镇
}

//经纬度
public 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;
    }
}

RegionConfig

class RegionConfig : IEntityTypeConfiguration<Region>
{
    public void Configure(EntityTypeBuilder<Region> builder)
    {
        builder.ToTable("T_Cities");
        builder.OwnsOne(c => c.Area, nb =>
        {
            nb.Property(e => e.Value)
            .HasColumnName("AreaValue")
            .HasComment("区域大小");
            nb.Property(e => e.Unit)
            .HasColumnName("AreaUnit")
            .HasMaxLength(20).IsUnicode(false)
            .HasConversion<string>().HasComment("单位(平方米/公顷)"); ;
        });

        builder.Property(e => e.Population).HasComment("人口");

        builder.OwnsOne(c => c.Location, nb =>
        {
            nb.Property(e => e.Longitude)
            .HasColumnName("Longitude")
            .HasComment("经度");
            nb.Property(e => e.Latitude)
            .HasColumnName("Latitude")
            .HasComment("维度");
        });

        builder.Property(c => c.Level).HasMaxLength(20)
            .IsUnicode(false).HasConversion<string>()
            .HasComment("城市级别(国家/省/市/城镇)");

        builder.OwnsOne(c => c.Name, nb =>
        {
            nb.Property(e => e.English).HasMaxLength(20).IsUnicode(false)            
           .HasColumnName("NameEnglish")
            .HasComment("英文");
            nb.Property(e => e.Chinese).HasMaxLength(20).IsUnicode(true)
            .HasColumnName("NameChinese")
            .HasComment("中文");
        });

    }
}

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

image-20220319153933559

(2)在EF Core中,实体的属性可以定义为枚举类型,枚举类型的属性在数据库中默认是以整数类型来保存的。EF Core中可以在Fluent API中用HasConversion()把枚举类型的值配置成保存为字符串。

image-20220319154006697

(4)查看数据库

执行命令add-mirgration 、update-database

image-20220319154259089

(5)简化值对象的比较操作

ExpressionHelper

class ExpressionHelper
{
	public static Expression<Func<TItem, bool>> MakeEqual<TItem, TProp>
(Expression<Func<TItem, TProp>> propAccessor, TProp? other)
	where TItem : class where TProp : class
	{
		var e1 = propAccessor.Parameters.Single();
		BinaryExpression? conditionalExpr = null;
		foreach (var prop in typeof(TProp).GetProperties())
		{
			BinaryExpression equalExpr;
			object? otherValue = null;
			if (other != null)
			{
				otherValue = prop.GetValue(other);
			}
			Type propType = prop.PropertyType;
			var leftExpr = MakeMemberAccess(propAccessor.Body, prop);
			Expression rightExpr = Convert(Constant(otherValue), propType);
			if (propType.IsPrimitive)
			{
				equalExpr = Equal(leftExpr, rightExpr);
			}
			else
			{
				equalExpr = MakeBinary(ExpressionType.Equal,
					leftExpr, rightExpr, false,
					prop.PropertyType.GetMethod("op_Equality")
				);
			}
			if (conditionalExpr == null)
			{
				conditionalExpr = equalExpr;
			}
			else
			{
				conditionalExpr = AndAlso(conditionalExpr, equalExpr);
			}
		}
		if (conditionalExpr == null)
		{
			throw new ArgumentException("There should be at least one property.");
		}
		return Lambda<Func<TItem, bool>>(conditionalExpr, e1);
	}
}

image-20220319154635087

posted @ 2022-04-08 17:20  peng_boke  阅读(377)  评论(0编辑  收藏  举报