EntityFramework Code-First—领域类配置之DataAnnotations

本文出自: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; }
}

    结果如下:

dataannotations key attribute

 

    我们也可以用用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; }     
}

    结果如下:

dataannotations key attribute

    注:当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; }
}

    结果如下::

dataannotations TimeStamp attribute

 

  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列已经被创建成不为空。

dataannotations required attribute

    

  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)。

dataannotations maxlength attribute

    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)的列,如下所示:

dataannotations maxlength attribute

    同理,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的表名

dataannotations table attribute

    我们也可以用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表

dataannotations table attribute

 

  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"列名。数据库如下:

dataannotations column attribute

    我们也可以使用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

dataannotations column attribute

 

  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外键列。

Entity Framework code-first example

    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作为外键,生成数据库如下所示:

Entity Framework code-first example

    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列。

dataannotations NotMapped attribute

    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 example

    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表中仅仅会创建两个外键了。如下图所示:

inverseproperty example

    当然,如果你想改外键名称,我们就给导航属性加上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; }}

    

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

    inverseproperty example

 

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

 

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351218.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 调试工具 PDB(Linux 环境下调试)

转载&#xff1a;http://blog.163.com/gjx0619126/blog/static/12740839320114995947700/ 在python中使用pdb模块可以进行调试 import pdb pdb.set_trace() 也可以使用python -m pdb mysqcript.py这样的方式 (Pdb) 会自动停在第一行&#xff0c;等待调试,这时你可以看看 帮助…

Ubuntu 更新源方法

安装完Ubuntu系统之后&#xff0c;面临的最主要的一个问题就是将apt安装源进行更新&#xff0c;因为在国内直接利用Ubuntu默认的安装源下载安装包速度慢&#xff0c;并且有的时候软件版本也比较旧。今天小编对Ubuntu更新源进行介绍&#xff1a;&#xff08;这里针对阿里源和清华…

PAT Basic 1002

1002 写出这个数 &#xff08;20 分&#xff09;读入一个正整数 n&#xff0c;计算其各位数字之和&#xff0c;用汉语拼音写出和的每一位数字。 输入格式&#xff1a; 每个测试输入包含 1 个测试用例&#xff0c;即给出自然数 n 的值。这里保证 n 小于 10​100​​。 输出格式&…

mybatis crud_MyBatis教程– CRUD操作和映射关系–第2部分

mybatis crud为了说明这一点&#xff0c;我们正在考虑以下示例域模型&#xff1a; 会有用户&#xff0c;每个用户可能都有一个博客&#xff0c;每个博客可以包含零个或多个帖子。 这三个表的数据库结构如下&#xff1a; CREATE TABLE user (user_id int(10) unsigned NOT NU…

MATLAB 排序函数(先按第一列排序(主排序)然后再按第二列排序(次排序))

利用 sortrows 函数实现MATLAB 先按第一列排序&#xff08;主排序&#xff09;然后再按第二列排序&#xff08;次排序&#xff09; A [8,9,6;5,5,2;2,5,8] sortrows(A)A 8 9 65 5 22 5 8ans 2 5 85 5 28 9 6

用PDB库调试Python程序

Python自带的pdb库&#xff0c;发现用pdb来调试程序还是很方便的&#xff0c;当然了&#xff0c;什么远程调试&#xff0c;多线程之类&#xff0c;pdb是搞不定的。用pdb调试有多种方式可选&#xff1a;1. 命令行启动目标程序&#xff0c;加上-m参数&#xff0c;这样调用myscrip…

数据操作

mysql> create table employee(-> id int primary key auto_increment,-> emp_name char(12) not null,-> sex enum(male,female) not null default male, #大部分是男的-> age int(3) unsigned not null default 28,-> hire_date date not null,-> post …

/usr/bin/ld: cannot find -l*** 这里***可以指lapack等

在Linux安装编译过程中有时会出现在如下形式的错误&#xff1a; /usr/bin/ld: cannot find -l***这里表示编译过程中找不到以下库名&#xff1a; lib库名(即***).so会发生这样的原因有以下三种情形&#xff1a; 系统没有安装相对应的lib 相对应的lib版本不对 lib&#xff0…

通过分区在Kafka中实现订单保证人

Kafka最重要的功能之一是实现消息的负载平衡&#xff0c;并保证分布式集群中的排序&#xff0c;否则传统队列中将无法实现。 首先让我们尝试了解问题陈述 让我们假设我们有一个主题&#xff0c;其中发送消息&#xff0c;并且有一个消费者正在使用这些消息。 如果只有一个使用…

破解栅栏密码python脚本

今天遇到一个要破解的栅栏密码&#xff0c;写了个通用的脚本 1 #!/usr/bin/env python2 # -*- coding: gbk -*-3 # -*- coding: utf_8 -*-4 # Author: 蔚蓝行5 # http://www.cnblogs.com/duanv6 e raw_input(请输入要解密的字符串\n)7 elen len(e)8 field[]9 for i in range(…

水稻已知os基因号,利用DAVIA进行GO功能富集分析

第1-5步&#xff1a; 已知水稻的基因&#xff08;os&#xff09;&#xff0c;进行功能注释 第6步 第七步&#xff1a; 第八步&#xff1a; 第九步&#xff1a; 第十步&#xff1a; 第十一步&#xff1a;

二,八,十,十六进制之间转换的相应方法

int num1 Integer.valueOf(n,16); //16进制转换成10进制 Integer.toHexString(Integer i); //10进制转换成16进制 补充&#xff1a;Integer.toHexString(Integer i);该方法得出的字符默认为小写&#xff0c;如果想得到大写结果&#xff0c;则变为Integer.toHexString(Integer i…

IDF实验室-图片里的英语

原题&#xff1a; 一恒河沙中有三千世界&#xff0c;一张图里也可以有很多东西。 不多说了&#xff0c;答案是这个图片包含的那句英文的所有单词的首字母。 首字母中的首字母要大写&#xff0c;答案格式是wctf{一坨首字母} 加油吧少年&#xff01;看好你哦~ writeup&#xff…

linux 终端调用MATLAB程序

linux 终端调用MATLAB程序 路径&#xff1a;/A/B/C/ 程序名称&#xff1a;xxx.m linux 终端调用MATLAB函数方法 cd /A/B/C/ matlab -nodisplay -nosplash -nodesktop -r "xxx;exit;"

2018-11-02 在代码中进行中文命名实践的短期目标

对中文命名的意义不再赘述, 请参看之前的对在代码中使用中文命名的质疑与回应. 去年中文命名实践的阻力和应对之后, 在一些小项目中继续实践了中文命名(Java/JS/Python等, 详见之前的专栏文章), 涉及领域不少但尚未形成明确的重点项目. 发现了一些在业务相关代码使用中文命名的…

Wireshark 命令行捕获数据

在 Wireshark 程序目录中&#xff0c;包含两个命令行捕获工具。这两个工具分别是 Dumpcap 和 Tshark。当不能以图形界面方式捕获数据时&#xff0c;可以在命令行使用 dumpcap 或 tshark 程序实施捕获。 一、使用 Dumpcap 捕获数据 执行 dumpcap -h 可以查看参数详情。 1、执行 …

zk ui_高级ZK:异步UI更新和后台处理–第2部分

zk ui介绍 在第1部分中&#xff0c;我展示了如何在ZK应用程序中使用服务器推送和线程来执行后台任务。 但是&#xff0c;这个简单的示例具有一个重大缺陷&#xff0c;这使其对于实际应用程序而言是一种不好的方法&#xff1a;它为每个后台任务启动了一个新线程。 JDK5引入了E…

学生管理系统 数据库版结果 查询student表中所有学生信息

1.创建school_java数据库 CREATE DATABASE schooljava; USE schooljava; CREATE TABLE student ( id INT(11), name VARCHAR(25), tel INT(11), sex VARCHAR(6) ); DESC student; java代码 package Mysql; import java.sql.Connection; import java.sql.DriverManager; imp…

如何查看思科交换机的出厂时间?

1.在交换机命令行运行show version 查看交换机的sn码 System serial number : FOC1723W0VP 2.SN码取出第四位至七位 以 FOC1723W0VP 为例 第四和第五位代表年份&#xff0c;第六和第七位代表当年的第XX周 &#xff08;范围是01至52周&#xff09; 1719962013 ; 23周 (注&…

Linux系统电脑非正常关机之后可能出现在登录界面循环的情况

Linux系统电脑非正常关机之后可能出现在登录界面循环的情况 例如&#xff1a; Ubuntu 18.04 有时会出现在登录界面循环&#xff0c;你输入密码&#xff0c;回车后又回到输入密码界面 &#xff0c;遇到这样的解决办法是直接进入命令行模式&#xff0c;然后看一下home文件夹&…