本节内容,部分为补充内容,部分涉及到9.3(P321-326)。主要NuGet包:无
一、使用值对象的两种情形及其EFCore映射配置
1、没有标识符的从属实体类
- 如商店的地理位置,包含经度和纬度,可以定义一个包含Longitude(经度)和Latitude(纬度)两个属性的Geo类型。
- 如商品的质量,除了double类型的数值外,还隐含着一个质量单位,可以定义一个包含Value(数值)和Unit(单位)两个属性的Weight类型。
- EFCore中,通过OwnsOne来进行配置
2、枚举类型
- 如员工的等级,除了定义为int类型(如1表示初级,2表示中级,3表示高级)外,可以定义一个枚举类型属性,来表示固定可选值范围。
- 枚举类型在数据库中默认是以int类型来保存的,但对于直接操作数据库的人员来说,可读性较差。
- EFCore中,通过HasConversion<string>将枚举类型配置为字符串。
二、使用值对象的案例
1、Region实体类及相关值对象类型和枚举类
//实体类-充血模型================================================================================ public class Region { public long Id { get; init; } //Id标识符 public MultiName Name { get; init; } //名称 public Area Area { get; init; } //面积 public Geo Location { get; init; } //地理位置 public RegionLevel Level { get; private set; } //地区级别 public long? Population { get; private set; } //人口 //私有无参构造函数,EFCore默认使用 private Region(){} //公有有参构造函数,外部创建对象时初始化 public Region(MultiName name, Area area, Geo location, RegionLevel level) { Name = name; Area = area; Location = location; Level = level; } public void ChangeLevel(RegionLevel level) { this.Level= level; } public void ChangePopulation(long population) { this.Population = population; } } //相关的值对象和枚举类型。值对象类型为不可变类型,推荐使用record========================== public record MultiName(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("纬度值无效!"); } if (latitude < -90 || latitude > 90) { throw new ArgumentException("经度值无效!"); } this.Longitude= longitude; this.Latitude= latitude; } }
2、EFCore的DbContext映射配置
public class MyDbContext:DbContext { public DbSet<Region> Regions { get; set; } ...... protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Region>(b => { b.ToTable("T_Regions"); //设置值对象Name b.OwnsOne(r => r.Name, vo => { vo.Property(n => n.English).HasMaxLength(20).IsUnicode(false); vo.Property(n => n.Chinese).HasMaxLength(20).IsUnicode(true); }); //设置值对象Area,同时将值对象Area类中Unit属性的枚举值映射为字符串 b.OwnsOne(r => r.Area, vo => { vo.Property(a => a.Unit).HasMaxLength(20).IsUnicode(false).HasConversion<string>(); }); //设置值对象Location b.OwnsOne(r => r.Location); //设置枚举值Level,映射为字符串 b.Property(r => r.Level).HasMaxLength(20).IsUnicode(false).HasConversion<string>(); }); } }
3、数据库迁移结果:①值对象按属性映射为多个字段,字段名称为“实体类属性名_值对象属性名”;②枚举类映射为字符类型字段
4、数据库操作及结果:
using var ctx = new MyDbContext(); //新增一条数据 //var region1 = new Region(name1,area1,geo1,RegionLevel.City); //region1.ChangePopulation(20000000); //ctx.Regions.Add(region1); //ctx.SaveChanges(); //查询数据 var region = ctx.Regions.FirstOrDefault(x => x.Name.Chinese == "广州"); Console.WriteLine(region); //将Region类修改为record类型,可打印字符串
特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍
标签:Core,ASP,get,对象,Area,枚举,5.3,类型,public From: https://www.cnblogs.com/functionMC/p/16926632.html