Entity Framework(三):使用特性(数据注解)创建表结构

一、理解Code First及其约定和配置

  传统设计应用的方式都是由下而上的,即我们习惯优先考虑数据库,然后使用这个以数据为中心的方法在数据之上构建应用程序。这种方法非常适合于数据密集的应用或者数据库很可能包含多个应用使用的业务逻辑的应用。对于这种应用,如果要使用EF的话,我们必须使用Database First方式。
  设计应用的另一种方法就是以领域为中心的方式(领域驱动设计DDD)。DDD是一种由上而下的方式,我们通过从实现应用所需要的领域模型和实体的角度思考,从而开始设计应用。数据库很少用来用于领域模型数据的持久化。使用DDD意味着我们要根据每个应用的需求来设计模型和实体,而且模型和实体是数据库可忽略的,即可以使用任何数据库技术实现保存。在这些情景中,我们应该使用EF的Code First方式,因为它允许我们创建POCO(Plain Old CLR Objects)作为持久化可忽略的领域模型。
使用Code First的优势在于:
  1、支持DDD。
  2、可以早早地着手开发,因为我们不必等待数据库的创建。
  3、持久化层(底层的数据库)的改变不会对现有的模型有任何影响。
  我们需要搞清楚的第一件事就是约定大于配置的概念。Code First方式期望模型类遵守一些约定,这样的话数据库持久化逻辑就可以从模型中提取出来。比如,如果我们给一个模型定义了一个Id属性,那么它就会映射到数据库中该类所对应的那张表的主键。这种基于约定的方式的好处在于:如果我们遵守了这些约定,那么我们就不必写额外的代码来管理数据库持久逻辑。但这样也存在缺点,缺点在于:如果没有遵守某个约定,那么EF就不会从模型中提取到需要的信息,运行时会抛异常。
  在这种没有遵守约定又要持久化数据的情况下,我们需要使用Code First的配置项提供关于模型一些额外的信息。比如,如果我们的模型类中没有Id属性作为主键,那么我们需要在想要的属性上加上[Key]特性,这样它就会被当作主键了。
注意:

EF使用模型类的复数的约定来创建数据表名,创建的列名和该类的属性名是一样的。

示例:

使用在EF应用一:Code First模式中介绍的使用方法创建一个数据库,其中实体类Product定义如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5
 6 namespace EFAppointmentCreateTable.Model
 7 {
 8     public class Product
 9     {
10         public int Id { get; set; }
11
12         public string ProductName { get; set; }
13
14         public double ProductPrice { get; set; }
15     }
16 }

数据库上下文Context类定义如下:

using EFAppointmentCreateTable.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;

namespace EFAppointmentCreateTable.EFContext
{
    /// <summary>
    /// 定义数据库上下文类,该类继承自DbContext
    /// </summary>
    public class Context:DbContext
    {
        /// <summary>
        /// 定义构造函数,继承自父类的构造函数,通过继承父类的构造函数来创建数据库
        /// 父类构造函数的参数是配置文件中配置的数据库连接字符串
        /// </summary>
        public Context()
            : base("DbConnection")
        { }

         //实体属性集合  根据实体名称的复数形式生成数据库的表名
        // 生成的表名是Products 和属性名Products无关
        // 即使把属性名改成Product,生成的表名还是Products 约定大于配置
        public DbSet<Product> Products { get; set; }
    }
}

创建后的数据库截图如下:

从上面的截图中可以看出,生成的数据库表名是实体Product的复数形式,使用默认约定生成Id主键列。

二、使用数据注解创建表结构

1、.NET数据类型和SQL数据类型之间的映射

首先EF这个ORM工具就是用来解决.NET类型和SQL Server列类型之间的阻抗失配的问题。比如,假设你在.net中定义了一个int类型的属性,那么你就可以认为EF已经安全地处理了这个列的定义并使用了合适的类型与之对应。记住一些.NET类型和SQL Server列类型之间的映射是很有必要的,下面是一些最常用的映射关系:

SQL Server Database Type .NET Type
Bigint Int64
binary,varbinary Byte[]
Bit Boolean
date,datetime,
datetime2,smalldatetime
DateTime
Datetimeoffset DateTimeOffset
decimal,money
smallmoney,numeric
Decimal
float Double
int Int32
nchar nvarchar,char
varchar
String
real Single
rowversion,timestamp Byte[]
smallint Int16
time TimeSpan
tinyint Byte
uniqueidentifier Guid

完整的映射列表可以参考SQL Server数据类型映射,如果你使用的是其他类型的数据库,你可以在网上自行查找。比如,,如果是Oracle,那么你可以在这里查找:oracle数据类型映射。

2、配置原始属性

以.NET中的string类型的属性开始讨论。SQL Server中的很多类型都会映射到.NET中的string类型,其他主流的RDBMS也是一样的。因此,决定如何存储字符串类型的信息是很重要的,很多关系数据库管理引擎都有多个字符存储类型,他们通常都有以字母N打头的字符类型,这个字母表示要存在这些列中的数据是Unicode数据,基于每个字符以2个字节的格式存储。因此,如果你的数据库中的列存储的是英文的话,就可以使用varchar或者char(可能会加速查询),如果使用的是中文的话,就要使用nvarchar或者nchar。此外,还可以使用带有var的字符类型来指定列的长度是可变的,不使用var的话,字符长度是不可变的。
在EF中有以下几种配置数据库结构的方式,分别是:
1、特性,也叫数据注解。
2、DbModelBuilder API。
3、配置伙伴类。

3、特性(数据注解)

这些特性类都是.NET的一部分,位于System.ComponentModel.DataAnnotaions命名空间下。下面我们修改在上一个例子中使用的Product实体类,修改后的Product实体类如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel.DataAnnotations;
 4 using System.ComponentModel.DataAnnotations.Schema;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8
 9 namespace EFDataAnnotations.Model
10 {
11     /// <summary>
12     /// 使用Table特性指定生成的表名
13     /// </summary>
14     [Table("Product")]
15     public class Product
16     {
17         //使用Key特性指示该列是主键列
18         [Key]
19         //使用Column特性指示生成的数据库表中的列名
20         [Column("ID")]
21         public int ProductId { get; set; }
22
23         /// <summary>
24         /// StringLength设置数据库表中列的长度
25         /// 指示ProductName字段的最大长度是10,最小长度是2
26         /// </summary>
27         [StringLength(10,MinimumLength=2)]
28         public string ProductName { get; set; }
29
30
31         public double ProductPrice { get; set; }
32
33         /// <summary>
34         /// DataType特性指示生成的数据库表中列的数据类型
35         /// </summary>
36         [DataType(DataType.DateTime)]
37         public DateTime ProductionTime { get; set; }
38
39         /// <summary>
40         /// NotMapped特性指示不把该属性映射到数据库表中,即在生成的表中没有d这一列
41         /// </summary>
42         [NotMapped]
43         public decimal d { get; set; }
44     }
45 }

运行程序后生成的数据库:

修改代码之后,我们将表的名字使用Table特性全部重新命名成了但是,将Product的主键通过Column特性更改为Id,Key特性指定它是主键,还通过StringLength指定了ProductName列的最大长度为10个字符,最小为2个字符。

此外,数据注解也可以用作验证特性。如果持久化数据时,模型对象的属性值和数据注解所标记的不一致,就会抛异常。

数据验证相关的数据注解:

特性 解释
Remote 使用 jQuery 验证插件远程验证程序的特性
FileExtension 验证文件扩展名
Compare 比较两个属性的值
RegularExpression 使用正则表达式验证
CustomValidation 自定义验证方法
DataType 指定要与数据字段关联的附加类型的名称
EmailAddress 电子邮件地址(相当于DataType(DataType.Email))
Phone 电话(相当于DataType(DataType.Phone))
CreditCard 信用卡号码(相当于DataType(DataType.CreditCard))
Url 验证URL(相当于DataType(DataType.Url))
MemberShipPassword 验证密码字段是否满足成员资格提供程序的当前密码要求

数据映射相关的数据注解:

特性 解释
Key 主键字段
Column 数据库列属性映射
NotMapped 不要创建对应的字段
Table 指定类将映射到的数据库表
ForeignKey 表示关系中用作外键的属性
DatabaseGenerated
指定属性应该映射到数据表中计算的列。也可以用于映射到自动增长的数据库表。

指定数据库生成属性值的方式(EF不追踪属性的变化)

Required 必填字段
MaxLength 指定属性中允许的数组或字符串数据的最大长度
MinLength 指定属性中允许的数组或字符串数据的最小长度
StringLength 指定最小和最大字符长度
Range 指定数值范围 

数据显示相关的数据注解:

特性 解释
DisplayName 指定本地化的字符串(习惯用语类)
Display 指定本地化的字符串(习惯用语属性)
DisplayFormat 设置数据字段的格式
ReadOnly 指定该特性所绑定到的属性是只读属性还是读/写属性
EditAble 指示数据字段是否可编辑
HiddenInput 指示是否应将属性值或字段值呈现为隐藏的 input 元素
ScaffoldColumn 指定类或数据列是否使用基架
UIHint 指定动态数据用来显示数据字段的模板

其他:

特性 解释
DisplayColumn 将所引用的表中显示的列指定为外键列
Description 可视化设计器在引用组件成员时可以显示指定的说明
(命名空间:System.ComponentModel.DescriptionAttribute)
时间: 2024-08-10 23:18:20

Entity Framework(三):使用特性(数据注解)创建表结构的相关文章

Entity Framework 6.x 学习之 - 创建带连接表的实体模型 with Database First

1. 创建数据库表 CREATE TABLE [Album] ( [AlbumId] [int] NOT NULL IDENTITY(1, 1), [AlbumName] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ) ON [PRIMARY] GO ALTER TABLE [Album] ADD CONSTRAINT [PK_Album] PRIMARY KEY CLUSTERED ([AlbumId]) ON [PRIMARY] GO

[翻译] - &lt;Entity Framework&gt; - 直接执行数据库命令

原文:[翻译] - <Entity Framework> - 直接执行数据库命令 纯属学习上的记录, 非专业翻译, 如有错误欢迎指正! 原文地址: http://msdn.microsoft.com/en-us/library/gg715124(v=vs.103) 使用 EF 4.1 或者更新版本, 你可以直接执行任何数据库命令. 在本节介绍的方法允许你对数据库执行原生的 SQL 命令. 通过 SQL 查询语句获取实体对象集 DbSet 类中的 SqlQuery 方法允许你执行一个返回实体对象

关于Entity Framework采用DB First模式创建后的实体批量修改相关属性技巧

Entity Framework采用DB First模式创建实体是比较容易与方便的,修改已创建的实体在个数不多的情况下也是没问题的,但如果已创建的实体比较多,比如10个实体以上,涉及修改的地方比较多的时候,那么这个时候采用可视化编器就不再那么方便了,而应该采用以XML的形式来呈现实体数据,然后用我们常用的编辑手段,复制.粘贴.剪切来快速实现批量修改,下面就来说说批量修改的方法: 1.找到Entity Framework采用DB First模式创建的文件,文件以.edmx结尾,如下图示: 2.选中

数据引擎 创建表完整语法,字段类型,约束条件

数据引擎 创建表完整语法,字段类型,约束条件 回顾: 1.设置密码与修改密码 mysqladmin -uroot -p password设置的密码 mysqladmin -uroot -p原密码 password新密码 2.破解密码 - 1.先关掉服务,杀死进程 - 2.跳过权限认证启动服务端 - 3.以游客的身份登录即可 3.制作服务 - 1.mysql --install - 2.net start mysql 4.语法: 库的操作: 增: create database 库名; creat

Oracle笔记(三) Scott用户的表结构

Oracle笔记(三) Scott用户的表结构 在Oracle的学习之中,重点使用的是SQL语句,而所有的SQL语句都要在scott用户下完成,这个用户下一共有四张表,可以使用: SELECT * FROM tab; 查看所有的数据表的名称,如果现在要想知道每张表的表结构,则可以采用以下的命令完成: DESC 表名称: 1.  部门表:dept № 名称 类型 描述 1 DEPTNO NUMBER(2) 表示部门编号,由两位数字所组成 2 DNAME VARCHAR2(14) 部门名称,最多由1

EF3:Entity Framework三种开发模式实现数据访问

前言 Entity Framework支持Database First.Model First和Code Only三种开发模式,各模式的开发流程大相径庭,开发体验完全不一样.三种开发模式各有优缺点,对于程序员没有哪种模式最好,只有哪种模式更适合.接下来我将分别使用这三种开发模式实现同一数据库模型的数据持久化功能.希望通过实践能帮助你找到更适合你的开发模式 Database First Database First开发模式指以数据库设计为基础,并根据数据库自动生成实体数据模型,从而驱动整个开发流程

浅谈Entity Framework中的数据加载方式

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 如果你还没有接触过或者根本不了解什么是Entity Framework,那么请看这里http://www.entityframeworktutorial.net/EntityFramework-Architecture.aspx,其中的一系列文

SQL Server 动态创建表结构

需求是,在word里面设计好表结构(主要在word中看起来一目了然,方便维护),然后复制sql 里面,希望动态创建出来 存储表结构的表 CREATE TABLE [dbo].[Sys_CreateTable]( [序号] [int] IDENTITY(1,1) NOT NULL, [中文名] [nvarchar](500) NULL, [英文名] [nvarchar](500) NULL, [类型.宽度.精度] [nvarchar](500) NULL, [默认值/描述] [nvarchar](

python3 开发面试题(创建表结构)6.9

纯sql语句写出: '''设计 图书管理系统 表结构: - 书 - 书名 - 作者 - 姓名 - 出版社 - 出版社名称 - 地址 一本书只能由一家出版社出版 --> 多对一(书对出版社) 一本书可以有多个作者,一个作者也可以写多本书 --> 多对多 ''' #答案CREATE TABLE book ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(64), publisher_id INT, FOREIGN KEY(publisher_id