EF Core ORM 框架
一、定义EF Core模型
EF Core使用约定,特性,Fluent API 在运行时构建实体模型
按照这三者的优先级高低排序分别是:Fluent API、特性、约定。
1. 约定(即按照EF Core默认的生成关系)
(1). 在实体中如果有名为ID的字段,或者实体名+ID的字段如:PersonID,那么EFCore生成的表会自动标识为主键。并且如果它的类型是int或Guid则会默认自增长
(2). EF Core 约定创建数据库表,表名称和DbContext中定义的DbSet属性名称是相同的
(3). 数据类型的约定
varchar:按字节存储,适合存储非Unicode字符数据。每个字符占用1个字节,适合存储英文字符或其他单字节字符集的字符。
nvarchar:按字符存储,适合存储Unicode字符数据。每个字符占用2个字节,适合存储多语言字符,包括中文、日文、韩文等。
2.特性
// 指定表名
[Table("Customers")]
public class Customer
{
// 主键,自增
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {
get; set; }
// 必填字段,最大长度 100
[Required]
[MaxLength(100)]
public string Name {
get; set; }
// 唯一索引
[Index(IsUnique = true)]
[StringLength(50, MinimumLength = 5)]
public string Email {
get; set; }
// 不映射到数据库
[NotMapped]
public string DisplayName => $"{
Name} ({
Email})";
// 复杂类型
public Address Address {
get; set; }
// 导航属性,一对多关系
[InverseProperty("Customer")]
public ICollection<Order> Orders {
get; set; } = new List<Order>();
// 并发检查字段
[ConcurrencyCheck]
public string LastUpdatedBy {
get; set; }
// 行版本(用于并发控制)
[Timestamp]
public byte[] RowVersion {
get; set; }
}
// 复杂类型
[ComplexType]
public class Address
{
[MaxLength(100)]
public string Street {
get; set; }
[MaxLength(50)]
public string City {
get; set; }
[MaxLength(10)]
public string PostalCode {
get; set; }
}
// 订单实体
[Table("Orders")]
public class Order
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {
get; set; }
[Required]
public DateTime OrderDate {
get; set; }
[MaxLength(200)]
public string Description {
get; set; }
// 外键
[ForeignKey("CustomerId")]
public Customer Customer {
get; set; }
public int CustomerId {
get; set; }
}
导航属性是实体类中的一个属性,用于表示该实体与其他实体之间的关系。它可以是:
引用导航属性:表示一对一(One-to-One)或一对多(One-to-Many)关系中的“一”方。
集合导航属性:表示一对多(One-to-Many)或多对多(Many-to-Many)关系中的“多”方。
3. Fluent API
Fluent API 相较于特性更加灵活。它的配置需要写在自定义的数据库上下文类中的OnModelCreating方法中。
public class AppDbContext : DbContext
{
public DbSet<Customer> Customers {
get; set; }
public DbSet<Order> Orders {
get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Customer 配置
modelBuilder.Entity<Customer>(entity =>
{
// 设置表名
entity.ToTable("Customers");
// 配置主键
entity.HasKey(c => c.Id);
// 配置唯一索引
entity.HasIndex(c => c.Email).IsUnique();
// 配置复杂类型
entity.OwnsOne(c => c.Address, a =>
{
a.Property(p => p.Street).HasMaxLength(100);
a.Property(p => p.City).HasMaxLength(50);
a.Property(p => p.PostalCode).HasMaxLength(10);
});
// 配置行版本
entity.Property(c => c.RowVersion).IsRowVersion();
// 配置并发检查字段
entity.Property(c => c.LastUpdatedBy).IsConcurrencyToken();
// 配置导航属性
entity.HasMany(c => c.Orders)