ValueObject 值对象
值对象:指实体类中,有的多个属性的关系密码不可分,但又不能独立作为实体类,因为这些属性依护属于实体。例如:位置 Location 包含 经度 longitude 和 纬度 latiude
在 EFCore 中提供了对于没有标识符的值对象进行映射的功能,即“从属实体类(owned entities)类型,我们只要在主实体类中声明从属实体类型的属性,然后使用 Fluent API 中的 OwnsOnet 等方法配置。
using CleanArchitectureApp.SharedKernel;
using CleanArchitectureApp.SharedKernel.Interfaces;
namespace CleanArchitectureApp.Core.RegionAggregate;
public class Region : EntityBase, IAggregateRoot
{
public MultilingualString Name { get; init; }
public Area Area { get; init; }
public RegionLevel Level { get; private set; }
public Int64? Population { get; private set; }
public Geo Location { get; set; }
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; set; }
public double Latitude { get; set; }
public Geo(double longitude, double latitude)
{
if (longitude < -180 || longitude > 180)
{
throw new ArgumentException("longitude invalid");
}
if (latitude < -90 || latitude > 90)
{
throw new ArgumentException("latitude invalid");
}
Longitude = longitude;
Latitude = latitude;
}
}
using CleanArchitectureApp.Core.RegionAggregate;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CleanArchitectureApp.Infrastructure.Data.Config;
public class RegionConfig : IEntityTypeConfiguration<Region>
{
public void Configure(EntityTypeBuilder<Region> builder)
{
builder.OwnsOne(c => c.Area, nb =>
{
nb.Property(e => e.Unit).HasMaxLength(20)
.IsUnicode(false).HasConversion<string>();
});
builder.OwnsOne(c => c.Location);
builder.Property(c => c.Level).HasMaxLength(20)
.IsUnicode(false).HasConversion<string>();
builder.OwnsOne(c => c.Name, nb =>
{
nb.Property(e => e.English).HasMaxLength(20).IsUnicode(false);
nb.Property(e => e.Chinese).HasMaxLength(20).IsUnicode(true);
});
}
}
using CleanArchitectureApp.Core.RegionAggregate;
using CleanArchitectureApp.SharedKernel.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace CleanArchitectureApp.Web.Api;
[Route("api/[controller]")]
[ApiController]
public class RegionController : ControllerBase
{
private readonly ILogger<RegionController> _logger;
private readonly IRepository<Region> _repository;
public RegionController(ILogger<RegionController> logger, IRepository<Region> repository)
{
_logger = logger;
_repository = repository;
}
[HttpPost]
public async Task<ActionResult<Region>> Create()
{
MultilingualString name1 = new MultilingualString("北京", "BeiJing");
Area area1 = new Area(16410, AreaType.SquareKM);
Geo loc = new Geo(116.4074, 39.904);
Region c1 = new Region(name1, area1, loc, RegionLevel.Province);
c1.ChangePopulation(21893100);
Region newRegion = await _repository.AddAsync(c1);
return Ok(newRegion);
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Region>>> GetList()
{
var list = await _repository.ListAsync();
return Ok(list);
}
}
跟据实体生成的表结构:


浙公网安备 33010602011771号