属性映射
属性使用 PropertyMappingAttribute
特性进行标记。它包含以下的属性:
ColumnName 标记数据库表中的字段名称。
Description 标记字段的备注。
IsPrimaryKey 标记是否为主键。
GenerateType 设置主键的生成方式。
IsDeletedKey 标记是否为逻辑删除标记。
IsNullable 标记是否为可空,非必要,但是使用 CodeFirst 模式需要设置。
DataType 标记字段的类型,非必要,但是使用 CodeFirst 模式需要设置。
Length 标记字段的长度,非必要,但是使用 CodeFirst 模式需要设置。
Precision 标记字段的精度,非必要,但是使用 CodeFirst 模式需要设置。
Scale 标记字段的小数位,非必要,但是使用 CodeFirst 模式需要设置。
IsConcurrencyToken 标记并发控制标识。
IsRowVersion 标记行版本号。
我们再来温习一下 实体模型 的实体类的定义,如下:
public partial class Products : LightEntity<Products>
{
[PropertyMapping(ColumnName = "product_id", IsPrimaryKey = true, GenerateType = IdentityGenerateType.AutoIncrement, IsNullable = false)]
public virtual int Id { get; set; }
[PropertyMapping(ColumnName = "product_name", Length = 40, IsNullable = false)]
public virtual string ProductName { get; set; }
[PropertyMapping(ColumnName = "supplier_id", IsNullable = true)]
public virtual int? SupplierID { get; set; }
[PropertyMapping(ColumnName = "category_id", IsNullable = true)]
public virtual int? CategoryID { get; set; }
[PropertyMapping(ColumnName = "quantity_pre_unit", Length = 20, IsNullable = true)]
public virtual string QuantityPerUnit { get; set; }
[PropertyMapping(ColumnName = "unit_price", IsNullable = true)]
public virtual decimal? UnitPrice { get; set; }
[PropertyMapping(ColumnName = "units_in_stock", IsNullable = true, DefaultValue = 34)]
public virtual short? UnitsInStock { get; set; }
[PropertyMapping(ColumnName = "units_on_order", IsNullable = true)]
public virtual short? UnitsOnOrder { get; set; }
[PropertyMapping(ColumnName = "reorder_level", IsNullable = true)]
public virtual short? ReorderLevel { get; set; }
[PropertyMapping(ColumnName = "discontinued", IsNullable = false)]
public virtual bool? Discontinued { get; set; }
public virtual EntitySet<OrderDetails> OrderDetailses { get; set; }
}
需要说明的是主键的 GenerateType 类型,大部分的数据库都有自增量,因此可以设置为 AutoIncrement,如果你需要手动指定主键值,则设为 None,比较特殊的情况如 Oracle
数据库,需要设为 Generator,此时,它会使用 标识生成服务 来生成。
另外,关于逻辑删除标记,一旦标记了某一个属性后,其仓储的 删除实体 将执行逻辑删除,仅将属性标记为 true,后续的查询均会过滤掉已经逻辑删除的数据。
行版本号和并发控制请参阅 行版本号及并发控制。
💡 属性分类
属性分基础属性 GeneralProperty
、关联属性 RelationProperty
两种,关联属性又分为实体属性 EntityProperty
、实体集属性 EntitySetProperty
、枚举引用属性 EnumProperty
和 属性引用属性 ReferenceProperty
。
使用 PropertyUnity
类可以获取指定实体类型某属性的元数据。它有以下方法:
GetProperties 获取实体类型的所有属性。
GetPrimaryProperties 获取实体类型的所有主键属性。
GetPersistentProperties 获取实体类型的所有可持久化属性,即排除关联属性之外的属性。
GetRelatedProperties 获取实体类型的所有关联属性。
下面的示例演示了如何获取实体类的属性元数据:
[TestMethod]
public void TestGetProperty()
{
//基础属性
var property = PropertyUnity.GetProperty(typeof(Products), nameof(Products.ProductName));
Assert.IsNotNull(property); //GeneralProperty
Assert.AreEqual("product_name", property.Info.ColumnName);
Assert.IsTrue(property.Info.IsNullable);
//子实体集属性
property = PropertyUnity.GetProperty(typeof(Products), nameof(Products.OrderDetailses));
Assert.IsNotNull(property); //EntitySetProperty
var relation = property as RelationProperty;
Assert.AreEqual(typeof(OrderDetails), relation.RelationalType)
//主键
property = PropertyUnity.GetPrimaryProperties(typeof(Products)).FirstOrDefault();
Assert.AreEqual(nameof(Products.Id), property.Name);
}
💡 小提示
如果你的属性和字段的名称是一致的,那么除了主键需要打上 PropertyMappingAttribute
特性外,其他属性都是可以不用标记的。对于基于 LightEntity<TEntity>
类型的实体类,Fireasy 会自动查找 virtual 的属性进行映射。如果有其他的需要,你可以改变 EntityMetadataUnity
类的 PropertyMetadataResolver 属性,实现 IPropertyMetadataResolver
接口来进行个性化映射。