值生成的模式
有3个可用于属性的值生成的模式:
- 无值生成
- 在添加时生成值
- 在添加或更新时生成值
1、无值生成
无值生成意味着您将始终提供要保存到数据库中的有效值。必须先将此有效值分配给新实体,然后才能将其添加到上下文中。
2、在添加时生成值
这意味着在添加新实体时生成值。
根据所使用的的数据库提供程序,值可能是由EF或数据库中的客户端生成的。如果值是由数据库生成的,则在将实体添加到DbContext时,EF可能会分配临时值。在执行SaveChanges()时,此临时值将被替换为数据库生成的值
如果您向上下文添加一个实体,并且该实体已为该属性分配了一个值,那么EF将尝试插入该值,而不是生成新值。如果没有为属性赋予一个CLR的默认值(string为null, int为0,Guid为Guid.Empty,等等),则认为该属性已被赋值。
约定:应用程序不提供值,则将short、int、long、或GUID类型的非复合主键设置为“给插入的实体生成值”。 数据库提供程序通常会负责必要的配置,例如,SQL Server 中的数字主键将自动设置为标识列。
注意:
如何为添加的实体生成值将取决于所使用的数据库提供程序。数据库提供程序可能会自动为某些属性类型设置值生成,但其他的可能需要您手动设置值生成的方式。
例如,在使用SQL Server时,将自动为GUID属性生成值(使用SQL Server的GUID顺序算法)。但是,如果在添加的时候指定DateTime属性,则必须为要生成的值设置一种方法。一种方法是配置GETDATE()的默认值。
可以将任何属性配置为“给插入的实体生成其值”,数据批注:
[Table("blog",Schema ="ER")] public class BlogModel { public int BlogId { get; set; } public string Url { get; set; } [NotMapped] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime LoadTime { get; set; } public List<PostModel> Posts { get; set; } }
Fluent API:
modelBuilder.Entity<BlogModel>() .Property(b => b.LoadTime) .ValueGeneratedOnAdd();
注意默认值:
在关系数据库中,可以使用默认值类配置列,如果插入的行没有没有该列的值,将使用默认值。在属性上配置默认值:
modelBuilder.Entity<BlogModel>() .Property(b => b.Url) .HasDefaultValue("www.baidu.com");
还可以指定用于计算默认值的SQL片段:
modelBuilder.Entity<BlogModel>() .Property(b => b.LoadTime) .HasDefaultValue("getdate()");
给属性指定默认值,会隐式的将属性配置为“在添加时生成值”模式。
3、在添加或更新时生成值
这意味着每次保存记录时(插入或者更新)都会生成一个新值。
与“在添加时生成值”模式一样,如果您在新添加的实体实例上为属性指定一个值,那么将插入该值,而不是正在生成的值。也可以在更新时设置显式值。
数据批注:
[Table("blog",Schema ="ER")] public class BlogModel { public int BlogId { get; set; } [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public string Url { get; set; } [NotMapped] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime LoadTime { get; set; } public List<PostModel> Posts { get; set; } }
Fluent API:
modelBuilder.Entity<BlogModel>() .Property(b => b.Url) .ValueGeneratedOnAddOrUpdate();
注意计算列:
大多数的关系数据库上,可以配置计算列。它通常引用其他列:
modelBuilder.Entity<PostModel>() .Property(b => b.ContentCount) .HasComputedColumnSql("LEN(Content)");
支持计算列的创建存储,是EF Core 5 的新特性!