本文出自:https://www.cnblogs.com/tang-tang/p/5510574.html

一、摘要

  EF Code-First提供了一个可以用在领域类或其属性上的DataAnnotation特性集合,DataAnnotation特性会覆盖默认的EF约定。

  DataAnnotation存在于两个命名空间里:

            System.ComponentModel.DataAnnotations

            System.ComponentModel.DataAnnotations.Schema

  注意: DataAnnotations只提供了一部分的配置选项,全部的配置选项在Fluent API中。

二、System.ComponentModel.DataAnnotations 包含的特性:

Attribute 描述
Key 标记一个属性,其将会在关系表中被映射成主键
Timestamp 标记一个属性,其将会在数据库中被映射成一个不为null的tiamestamp(时间戳)列
ConcurrencyCheck 这个属性允许你标记一个或多个属性,被标记的属性将会在用户编辑或删除entity的时候进行并发检查
Required 强制约束,该属性必须有数据,不能为null(同样适用MVC)
MinLength 确保数组或字符串长度达到最小长度
MaxLength 数据库中列的长度的最大值
StringLength 在数据字段中指定字符允许的最大长度和最小长度

三、System.ComponentModel.DataAnnotations.Schema 包含的特性:

Attribute 描述
Table 指定被映射的类在数据库生成的表名
Column 指定被映射的属性在表中的列名和数据类型
Index 在指定列上创建索引(仅EF6.1以上版本支持)
ForeignKey 给导航属性指定外键属性
NotMapped 标记的属性不会被映射到数据库
DatabaseGenerated 指定的属性将会映射成数据库表中的计算列,所以这个属性应是只读的。也可以用在把属性映射成标识列(自增长列)
InverseProperty 当两个类之间包含多重关系的时候,默认约定会排列组合他们的导航属性组合并一一创建外键,InverseProperty可以标记实际的主外键关系,从而过滤掉因排列组合出来的无用外键
ComplexType 标记一个类为复杂类型

四、特性详细介绍

  1、Key

    Key特性应用在类的属性上。Code-First默认约定将名称是"Id"或者{类名}+"Id"的属性创建为一个主键列,Key特性覆写了默认约定,我们可以把任何想要成为的主键的属性标记为Key而不管它是什么名称。

    代码如下:

using System.ComponentModel.DataAnnotations;public class Student
{public Student(){ }[Key]public int StudentKey { get; set; }public string StudentName { get; set; }
}

    结果如下:

    我们也可以用用Key特性和Column特性创建混合主键,如下代码所示:

using System.ComponentModel.DataAnnotations;
public class Student
{public Student(){ }[Key][Column(Order=1)]public int StudentKey1 { get; set; }[Key][Column(Order=2)]public int StudentKey2 { get; set; }public string StudentName { get; set; }
}

    结果如下:

    注:当Key特性应用在单整型类型的属性上时,会将其创建为一个标识列,而混合键无论它是不是整型类型,都不会创建标识列。Key特性除了无符号整型(unsinged integers),可以应用在如string、datatime、decimal等任何数据类型上。

  2、TimeStamp

    TimeStamp特性只能用在数据类型为byte array的属性上,TimeStamp特性会在数据库表中创建一个timestamp属性的列,Code-First自动使用TimeStamp列进行并发检查。

    (关于并发检查,可以参考Gyoung的笔记:Entity Framework 并发处理)

    代码如下:

using System.ComponentModel.DataAnnotations;
public class Student
{public Student(){ }public int StudentKey { get; set; }public string StudentName { get; set; }[TimeStamp]public byte[] RowVersion { get; set; }
}

    结果如下::

  3、ConcurrencyCheck

    当EF对表执行update命令时,Code-First会把标记了ConcurrencyCheck特性的列中的值插入到SQL语句的“where”子句中来进行并发检查。

    如下代码:

using System.ComponentModel.DataAnnotations;
public class Student
{public Student(){}public int StudentId { get; set; }[ConcurrencyCheck]public string StudentName { get; set; }
}

    如上所示,StudentName属性上标记了ConcurrencyCheck特性,所以Code-First会在update命令中把StudentName列包含进去以进行乐观并发检查(有关乐观并发和悲观并发,上面Gyoung的笔记有介绍,这里就不多讨论)。如下代码所示:

exec sp_executesql N'UPDATE [dbo].[Students]
SET [StudentName] = @0
WHERE (([StudentId] = @1) AND ([StudentName] = @2))
',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Steve',@1=1,@2=N'Bill'
go 

    注意:TimeStamp特性只能用在single byte数组属性上,然而ConcurrencyCheck特性可以用在任何数量和任何数据类型的属性上。

  

  4、Required

    应用了Required特性的属性,将会在数据库表中创建一个不为null的列,需要留意的是,Required也是MVC的验证特性。

      代码如下:

using System.ComponentModel.DataAnnotations;public class Student
{public Student(){ }public int StudentID { get; set; }[Required]public string StudentName { get; set; }}

    在数据库中,StudentName列已经被创建成不为空。

    

  5、MaxLength

    Maxlength特性用在String或array类型的属性上,EF Code-First将会把列的大小设置成指定值。值得注意的是,Maxlength也是MVC的验证特性。

      代码如下:

using System.ComponentModel.DataAnnotations;public class Student
{public Student(){ }public int StudentID { get; set; }[MaxLength(50)]public string StudentName { get; set; }}

    因为StudentName属性被指定了[Maxlength(50)]特性,所以在数据库中StudentName列被创建成nvarchar(50)。

    Entity Framework也会验证被标记了MaxLength特性的属性的值,如果该值大于被标记的最大值,EF将会抛出EntityValidationError。

  6、MinLength

    MinLength特性是EF的一个验证特性,其在数据库模式中不起作用。如果我们对标记了MinLength特性的属性赋值(string或者array),其长度小于指定的最小值,那么EF仍然会抛出EntityValidationError。

    MinLength特性可以和MaxLength特性一起使用,如下代码所示:

using System.ComponentModel.DataAnnotations;public class Student
{public Student(){ }public int StudentID { get; set; }[MaxLength(50),MinLength(2)]public string StudentName { get; set; }}

     如上代码所示,StudentName属性取值指定了只能是2-50个字符长度之间。

  7、StringLength

    StringLength应用在string类型的属性上,EF Code-First将会用StringLength指定的长度设置列的大小。和Required以及Maxlength一样,StringLength也是MVC的验证特性。

    看下面的代码:

using System.ComponentModel.DataAnnotations;public class Student
{public Student(){}public int StudentID { get; set; }[StringLength(50)]public string StudentName { get; set; }}

    根据代码中StudentName属性的[StringLength(50)]特性,在数据库中,将会创建一个nvarchar(50)的列,如下所示:

    同理,EF也将会验证StringLength特性中的值,如果用户输入的值大于指定的长度,将会抛出EntityValidationError。

  8、Table

    Table特性应用在类上,默认的Code-First约定将会创建一个和类名同名的表名,Table特性覆写默认的约定,EF Code-First将会创建一个以Table特性里指定的字符串为名称的表。

    代码如下:

using System.ComponentModel.DataAnnotations.Schema;[Table("StudentMaster")]
public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }}

    如上所示,Student类上应用了Table["StudentMaster"]特性,所以Code-First会覆写默认的约定,创建一个名称为StudentMaster的表名

    我们也可以用Table特性为表指定一个架构名,代码如下所示:

using System.ComponentModel.DataAnnotations.Schema;[Table("StudentMaster", Schema="Admin")]
public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }}

    数据库如下,Code-First将会在Admin架构下创建一个StudentMaster表

  9、Column

    Column特性应用在类的属性上,和Table特性一样,如果不指定Column特性的值,将会默认创建和属性同名的列,否则就会创建指定的值。

    看如下代码:

using System.ComponentModel.DataAnnotations.Schema;public class Student
{public Student(){ }public int StudentID { get; set; }[Column("Name")]public string StudentName { get; set; }}

    如上所示,Column["Name"]特性应用在StudentName属性上,所以Code-First将会创建一个以"Name"为名的列来代替默认的"StudentName"列名。数据库如下:

    我们也可以使用Column特性为列指定排序(order)和类型(type),代码如下:

    

using System.ComponentModel.DataAnnotations.Schema;public class Student
{public Student(){ }public int StudentID { get; set; }[Column("Name", Order=1, TypeName="varchar")]public string StudentName { get; set; }}

    上面的代码在数据库Students表中创建了一个属性为varchar,排序第一的列Name

  10、ForeignKey

    ForeignKey特性应用在类的属性上。默认的Code-First约定预料外键属性名与主键属性名匹配,如下代码:

public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }//Foreign key for Standardpublic int StandardId { get; set; }public Standard Standard { get; set; }
}public class Standard
{public Standard(){ }public int StandardId { get; set; }public string StandardName { get; set; }public ICollection<Student> Students { get; set; }}
}

    如上代码所示,Student类包含了外键属性StandardId,其又是Standard类的主键属性,这样,Code-First将会在Students表中创建一个StandardId外键列。

    ForeignKey特性覆写了默认约定,我们可以把外键属性列设置成不同名称,代码如下:

public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }//Foreign key for Standardpublic int StandardRefId { get; set; }[ForeignKey("StandardRefId")]public Standard Standard { get; set; }
}public class Standard
{public Standard(){ }public int StandardId { get; set; }public string StandardName { get; set; }public ICollection<Student> Students { get; set; }}

    如上代码所示,Student类包含了StandardRefId外键属性,我们使用ForeignKey["StandardRefId"]特性指定在Standard导航属性上,所以Code-First将会把StandardRefId作为外键,生成数据库如下所示:

    ForeignKey特性也可以用在外键属性上,只要指定好它的导航属性,即Standard属性,如下所示:

public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }//Foreign key for Standard
    [ForeignKey("Standard")]public int StandardRefId { get; set; }public Standard Standard { get; set; }
}public class Standard
{public Standard(){ }public int StandardId { get; set; }public string StandardName { get; set; }public ICollection<Student> Students { get; set; }}

    这段代码和上面把ForeignKey特性定义在Standard属性上的效果是一样的,在数据库生成的Students表都创建了StandardRefId外键列。

  11、NotMapped

    NotMapped特性用在类的属性上,默认Code-First约定会为那些所有包含了getter和setter的属性创建列,

      NotMapped可以覆写默认的约定,让那些标记了NotMapped特性的属性不会在数据库里创建列。代码如下:

using System.ComponentModel.DataAnnotations;public class Student
{public Student(){ }public int StudentId { get; set; }public string StudentName { get; set; }[NotMapped]public int Age { get; set; }
}

    如上代码所示,NotMapped特性应用在Age属性上,所以Code-First不会在Students表中创建Age列。

    Code-First也不会为那些没有getter和setter的属性创建列,在下面代码例子中,Code-First不会为FirstName和Age创建列。

using System.ComponentModel.DataAnnotations;public class Student
{public Student(){ }private int _age = 0;public int StudentId { get; set; }public string StudentName { get; set; }public string FirstName { get{ return StudentName;}  }public string Age { set{ _age = value;}  }}

  12、InverseProperty

    我们已经知道,如果类中没有包含外键属性,Code-First默认约定会创建一个{类名}_{主键}的外键列。当我们类与类之间有多个关系的时候,就可以使用InverseProperty特性。

      代码如下:

public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }public Standard CurrentStandard { get; set; }public Standard PreviousStandard { get; set; }
}public class Standard
{public Standard(){ }public int StandardId { get; set; }public string StandardName { get; set; }public ICollection<Student> CurrentStudents { get; set; }public ICollection<Student> PreviousStudents { get; set; }}}

    如上代码所示,Student类包含了两个Standard类的导航属性,同样的,Standard类包含了两个Student类的集合导航属性,Code-First将会为这种关系创建4个列。如下所示:

    InverseProperty覆写了这种默认约定并且指定对齐属性,下面的代码在Standard类中使用InverseProperty特性修复这个问题。

public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }public Standard CurrentStandard { get; set; }public Standard PreviousStandard { get; set; }
}public class Standard
{public Standard(){ }public int StandardId { get; set; }public string StandardName { get; set; }[InverseProperty("CurrentStandard")]public ICollection<Student> CurrentStudents { get; set; }[InverseProperty("PreviousStandard")]public ICollection<Student> PreviousStudents { get; set; }}}

    如上代码所示,我们在CurrentStudents和PreviousStudents属性上应用了InverseProperty特性,并且指定哪个Student类的引用属性属于它,所以现在,Code-First在Student表中仅仅会创建两个外键了。如下图所示:

    当然,如果你想改外键名称,我们就给导航属性加上ForeignKey特性,如下代码所示:

public class Student
{public Student(){ }public int StudentID { get; set; }public string StudentName { get; set; }public int CurrentStandardId { get; set; }public int PreviousStandardId { get; set; }[ForeignKey("CurrentStandardId")]public Standard CurrentStandard { get; set; }[ForeignKey("PreviousStandardId")]public Standard PreviousStandard { get; set; }
}public class Standard
{public Standard(){}public int StandardId { get; set; }public string StandardName { get; set; }[InverseProperty("CurrentStandard")]public ICollection<Student> CurrentStudents { get; set; }[InverseProperty("PreviousStandard")]public ICollection<Student> PreviousStudents { get; set; }}

    

    上面的代码将会创建出下面的数据库表和列,我们可以看出,外键的名称已经改变了。

    

  到此,DataAnnotation已经介绍完了,如果有什么不明白,或者我没讲清楚的地方,请大家留言~如有错误,也希望大神指出,不甚感激!

转载于:https://www.cnblogs.com/JamelAr/p/10469543.html

EntityFramework Code-First—领域类配置之DataAnnotations相关推荐

  1. Spring基于@Configuration的类配置的内部源码实现

    概述 Spring容器启动时,即ApplicationContext接口实现类的对象实例执行refresh方法时,主要是通过执行ConfigurationClassPostProcessor这个Bea ...

  2. jdbc工具类 配置版本 20210412_222527.mp4

    jdbc工具类 配置版本 20210412_222527.mp4 编写jdbc工具类,要求,代码要灵活,可随时变更登陆用户与连接的数据库 分析: 可以使用基本的写法加上配置 让配置来提供变化的数据 避 ...

  3. 【已解决】联想小新14无线图标消失 | 网络适配器有感叹号 | Windows仍在设置此设备的类配置(代码56)的解决方法

    我的电脑型号是联想小新Air-14IIL 2020,起因是系统让我更新驱动(具体什么驱动忘记了),更新后发现网络里只剩飞行模式,没有WLAN,也没有移动热点了,查看设备管理器发现网络适配器下所有驱动都 ...

  4. 复现上篇文章故障得知:网卡错误56,Windows 仍在设置此设备的类配置的原因

    上篇文章:网络属性里的残留网络服务卸载错误0x8007007e导致卡巴斯基安装到klim6.sys错误27300回滚 里提到虚拟机卸载残留VMware Bridge Protocol导致卡巴斯基安装k ...

  5. windows仍在设置此类设备的类配置,代码56

    windows仍在设置此类设备的类配置,代码56 问题 解决办法 以下是我的操作步骤 总结 问题 网络适配器中的驱动程序上全部出现黄色感叹号(VM开头的除外). 解决办法 以下是我的操作步骤 第一步: ...

  6. 修复无限网卡驱动报错:windows仍在设置此设备的类配置(代码56)

    寻找问题:针对win10系统设置里边无法找到"WLAN"及"以太网"问题,先在设备管理器中找到无限网卡,"此电脑"或者"我的电脑& ...

  7. 【解决】无线网卡windows仍在设置此设备的类配置,代码56解决方法

    置顶个联系方式 文章觉得海星的话,可以来群里找桃子交流技术或者普通乱聊= = 挂Q: 398529803 挂群:820080257 1 问题 无线网卡windows仍在设置此设备的类配置,代码56 2 ...

  8. 【解决】无线网卡windows仍在设置此设备的类配置,代码56

    症状:笔记本wifi列表为空,设备管理器无线网卡显示[无线网卡windows仍在设置此设备的类配置,代码56] 解决方法:下载ccleaner,扫描注册表,修复问题.再扫描一遍,修复问题.完成. 原因 ...

  9. Windows 仍在设置此设备的类配置。 (代码 56)

    家里电脑有线网卡出现"Windows 仍在设置此设备的类配置. (代码 56)",解决方法:键盘按win+r,弹出运行窗口,输入"redegit",进入注册表, ...

最新文章

  1. sbt创建play framework(play!)scala web项目
  2. 三十二楼层选几层最好_买房楼层怎么选?建筑学家建议:一栋楼不管几层,最好避开这3层...
  3. Linux查看和控制进程
  4. 计算机常用维护知识,电脑怎么维护?电脑日常维护小常识
  5. 分布式光伏贷款欲破冰 多家银行推出相关业务
  6. Tomcat 学习过程4
  7. cv2.show()cv2.waitKey()cv2.VideoCapture()的使用
  8. python 面向对象的封装_Python面向对象封装操作案例详解
  9. 段描述符和段选择符解析
  10. Windows Server 2008 使用蓝牙的问题
  11. Kubernetes 持续集成 SpringCloud
  12. 维护最短路径条数和途径点的权值累加
  13. OI生涯回忆录(Part6:至高一NOIP考试结束)
  14. 怎么做拼多多活动|成都百择
  15. 怎么让计算机联网,如何让电脑自动联网
  16. Wavelets: Seeing the forest and the trees
  17. Linux系统下,CPU信息详解(cpuinfo,多核,多线程)
  18. Mysql之group by 和order by 一起用时的排序问题,先排序然后再同组
  19. 爬取动态网页数据的软件-抓取动态网页数据的工具
  20. 虚拟wifi无网络访问的解决办法

热门文章

  1. 用于zsh的插件incr(目录提示和补全)
  2. Linux 命令之 vmstat 命令-显示虚拟内存状态
  3. c语言iota怎么用,C++ std::iota用法及代码示例
  4. datax 持续数据同步_采用DataX实现多表增量数据同步
  5. matlab 传输速率,处理速率转换 - MATLAB Simulink - MathWorks 中国
  6. matlab中的导函数驻点,Matlab用导数作定性分析
  7. apache geode项目结构_Apache Flink-基于Java项目模板创建Flink应用(流计算和批计算)...
  8. oracle agile 性能,Oracle Agile PLM安全漏洞(CVE-2016-3554)
  9. 3-pycharm找不到库的解决办法
  10. hd-sdi转hdmi转换器产品规格参数及接口定义详解