复杂的数据模型

数据注解:

通过在数据模型上加入注解 指定显示格式、验证和数据库映射规则。

DataType 属性用于指定一个比数据库特有类型更加具体的类型。

DataType属性能够启用HTML功能。(比如显示日历控件,正确的货币符号或者电子邮件链接,一些客户端输入验证)

默认情况一下,浏览器将使用基于本地的正确格式来渲染数据。

1.StringLength:设置了在数据库中的最大长度,并提供了客户端和服务端验证。也能够在StringLength属性中指定minimum string lengh 最小值,但指定最小值不会更改数据库的结构,也不能使得Fluent API来配置。

[StringLength(50,ErrorMessage ="{0}不能多于50个字符",MinimumLength =1)]
public string FirstMidName { get; set; }

2.RegularExpression:正则表达式。

maxlength:属性提供与StringLength()相同的功能,但不提供客户端验证。

3.Required:对于非空类型,Required属性是不必要的,如(DateTime,int,double ,float),它们自动看成非空字段。

 

4.Display:Display属性指定 了文本框的标题。

5. Range:

5 计算属性:计算属性只有get访问器而没有set访问器,它不会在数据库中创建。

he MaxLength attribute provides functionality similar to the StringLength attribute but doesn't provide client side validation.

Maxlength 特性提供了与StringLength相似的功能,但不提供客户端和服务端的验证。

 

数据库的模型改变需要更改在数据库中的结构,你可能通过迁移来更改数据库的结构而不丢失通过UIt添加的任何数据。

dotnet ef migrations add MaxlengthOnNames

迁移文件名字的时间戳前缀是为了给迁移排序

更新数据库CLI命令:dotnet ef database update

你能够创建多个迁移,然后再运行update-database命令,然后,所有的迁移都会按照它们创建的先后顺序被运用。

Column 列属性,可以更改映射到数据库的列名,也可以更改映射到数据库的SQL类型。

你能够使用数据注解 来控制类及期属性映射到数据库的方式 。引入 Column属性需要 引入 命名空间System.ComponentModel.DataAnnotations.Schema;

 [StringLength(50,ErrorMessage ="{0}不能多于50个字符",MinimumLength =1)]

[Column("FirstName")]
public string FirstMidName { get; set; }

完整的Students类:

public class Student
{
public int ID { get; set; }

[Required(ErrorMessage ="{0}不能为空")]
[StringLength(50,ErrorMessage ="{0}不能多于{1}个字符")]
[Display(Name = "姓")]
public string LastName { get; set; }

[Required(ErrorMessage ="{0}是必需的")]
[StringLength(50,ErrorMessage ="{0}不能多于{1}个字符",MinimumLength =1)]
[Column("FirstName")]
[Display(Name ="名")]
public string FirstMidName { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString ="{0:yyyy-MM-dd}",ApplyFormatInEditMode =true)]
[Display(Name ="入学日期")]
public DateTime EnrollmentDate { get; set; }

[Display(Name="全名")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}

//在模型类里面定义导航属性的时候,可以不使用 virtual关键字。
public virtual ICollection<Enrollment> Enrollments { get; set; }
}

如果一个导航属性拥有多个实体,能够指定 ICollection<T>或者List<T>、HashSet<T>.如果你指定 为ICollection<T>,EF将会创建HashSet<T>集合。

 如果一个实体的属性命名为ID或 ClassNameID,它被视为主键。

如果想要其它名字的属性被视为主键,就需要加上[Key]注解,EFf对待这种主键 视为不是数据库 产生,因为此列用来标识关系。

一对 零或一的关系需要在各自的导航属性上相互引用。

默认情况一下,EF假定主键值由数据库生成。然而在一些情况下,你希望由用户指定。可以使用[DatabaseGenerated(DatabasegeneratedOption.None)]注解属性。 [DatabaseGenerated]属性也被用于生成默认的值,如用于记录创建或更新行的日期的数据库列的情况。

 

通常Column[]注解列映射不是需要的,因为EF会根据定义的数据属性的的CLR类型,选择适合的SQL数据类型。

通过约定,EF对于非空外键和多对多关系 启用了级联删除。这可能引发循环的级联删除规则。在你尝试添加一个迁移的时候,这可能导致产生异常。

Fluent API关闭级联删除:

modelBuilder.Entity<Department>() .HasOne(d => d.Administrator) .WithMany() .OnDelete(DeleteBehavior.Restrict);//使用Fluent API配置部门与管理员间

one -0and many关系。

数据库的连接表是需要的,实体集也需要定义。在数据模型的早期阶段一个没有负载的纯连接表常常在后来变成有负载的。

对于多对多关系,EF6.x支持隐匿的连接表。而EF Core不支持。需要手动的定义多对多关系的数据模型。

 

由于外键不可空并且一起唯一地标识表的每一行,因此不需要单独的主键。 InstructorID和CourseID属性应该用作复合主键。 识别EF的复合主键的唯一方法是使用Fluent API(不能通过使用属性来完成)。 您将在下一节中看到如何配置复合主键。
组合键确保虽然一个课程可以有多行,而一个教师可以有多个行,但是同一个教师和课程不能有多行。 注册连接实体定义了自己的主键,因此可以使用此类重复项。 要防止此类重复,您可以在外键字段上添加唯一索引,或使用类似于CourseAssignment的主复合键配置Enrollment

//配置连接表 的主键为组合主键,这里,只能通过Fluent API配置,不能使用属性来配置。
modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });

 你也可以使用Fluent AP来代替属性,I指定大多数的格式、验证和映射规则。一些属性不能代替如 MinimunLenth,因此它不会更改数据库的结构,而只是添加了客户端和服务端的验证规则。

一些开发人员更喜欢专门使用流畅的API,以便他们可以保持实体类“干净”。 如果需要,您可以混合属性和流畅的API,并且有一些自定义只能通过使用流畅的API来完成,但一般来说,建议的做法是选择这两种方法中的一种并尽可能一致地使用它。 如果您同时使用两者,请注意,只要存在冲突,Fluent API就会覆盖属性。

 

PMC:增加迁移,Add-Migration <name>

Remove-Migration <name>

 在Initializer类中去除 //Context.Database.EnsureCreated;  因为它能保证数据库能创建,但不能使用迁移来创建数据库。

运行应用程序将触发 Initializer代码 初始化填充数据库。

posted on 2018-08-08 18:51  众里寻他千万度  阅读(137)  评论(0)    收藏  举报

导航