上一篇介绍了实体类型,这一篇就介绍一下实体属性
EF的小知识点,实在是多,所以写篇文章,整理一下,也方便查看知识点。
虽然可以通过读取EF的源码了解这些,但是读取一堆满屏飞的泛型类,还真是不容易呀
上一篇中 我讲了如何指定数据表名称,规避实体类型,但是没有说 实体属性。下面详细说明。
通过给属性添加NotMapped。类似于排除实体类型
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
[NotMapped]
public DateTime LoadedFromDatabase { get; set; }
}
也可以通过下面的代码
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Ignore(b => b.LoadedFromDatabase);
}
我个人是比较推荐使用代码直接show的。
有时候代码里面的列名称和数据库里面的不一样或者俩边要求的命名方式不一致咋办?这种情况也是存在的,有时候别人起的数据库名称拼音+大写字母 很让人头疼,我们就可以通过这个功能规避掉,下面的是通过添加Column特性指定其具体的名称
public class Blog
{
[Column("blog_id")]
public int BlogId { get; set; }
public string Url { get; set; }
}
当然我们也可以这样
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(b => b.BlogId)
.HasColumnName("blog_id");
}
既然都可以指定列名称了,当然也就可以指定数据库类型了。 一般情况下我们使用decimal都是用小数点精度后两位,如果要3位,4位怎么办??这个时候就需要我们指定具体的精度了。
EF提供了俩种方式,一种是数据批注,另一种就是Fluent API
public class Blog
{
public int BlogId { get; set; }
[Column(TypeName = "varchar(200)")]
public string Url { get; set; }
[Column(TypeName = "decimal(5, 2)")]
public decimal Rating { get; set; }
}
或者
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(eb =>
{
eb.Property(b => b.Url).HasColumnType("varchar(200)");
eb.Property(b => b.Rating).HasColumnType("decimal(5, 2)");
});
}
批注的格式和你的数据库匹配即可,不是所有数据库都支持上面的写法的,上面的写法是SQL Server的写法,其他的类似
收线要指定不是所有的类型都支持最大长度这个功能的,这个功能主要针对于数组类型。
public class Blog
{
public int BlogId { get; set; }
[MaxLength(500)]
public string Url { get; set; }
}
或者
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(b => b.Url)
.HasMaxLength(500);
}
需要指定数据精度的主要位俩种类型,decimal和datetime。
对于 decimal
属性,精度定义表示列将包含的任何值所需的最大位数,而 scale 定义所需的最大小数位数
对于 DateTime
属性,精度定义表示秒的小数部分所需的最大位数,并且不使用小数位数。
下面的示例,指定Score位精度14,2位小数。指定LastUpdtaed位Datetime2(3)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(b => b.Score)
.HasPrecision(14, 2);
modelBuilder.Entity()
.Property(b => b.LastUpdated)
.HasPrecision(3);
}
从C# 8.0开始支持了null的引用类型。之前是只支持可空的值类型。
当我们没有开启可为null 类型时我们需要手动指定那些属性是必须的
public class CustomerWithoutNullableReferenceTypes
{
public int Id { get; set; }
[Required] // Data annotations needed to configure as required
public string FirstName { get; set; }
[Required]
public string LastName { get; set; } // Data annotations needed to configure as required
public string MiddleName { get; set; } // Optional by convention
}
而当我们开启了可空引用类型后,相反,我们需要手动指定哪些类型是可为空的
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; } // Required by convention
public string LastName { get; set; } // Required by convention
public string? MiddleName { get; set; } // Optional by convention
public Customer(string firstName, string lastName, string? middleName = null)
{
FirstName = firstName;
LastName = lastName;
MiddleName = middleName;
}
}
个人建议一般情况下手动指定是否可为空,而不要让框架推断,因为你的代码很有可能被第三个人莫名其妙的修改掉。这也是你避免不了的。
你可以这样实现
public class Blog
{
public int BlogId { get; set; }
[Required]
public string Url { get; set; }
}
也可以这样实现
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(b => b.Url)
.IsRequired();
}
在EFCore 5.0中,新增了该功能,但是我们要知道,不是所有的数据库都支持该功能的,因为有些数据库区分大小写而有些数据库不区分大小写,这是一个容易让人犯错的操作。
modelBuilder.Entity().Property(c => c.Name)
.UseCollation("SQL_Latin1_General_CP1_CI_AS");
关于排序规则的详细介绍,请看详细介绍