I.EF的默认映射

上节我们创建项目,通过定义实体类就可以自动生成数据库,并且EF帮我们自动设置了数据库的主键、外键以及表名和字段的类型等,这就是EF的默认映射。具体分为:

  1. 数据库映射:Code First 默认会在本地的SQL Expression数据库中建立一个和DbContext的子类的全名相同的数据库,全名指的是命名空间加上类名。当然前面我们在配置文件里指定了要连接的数据库;
  2. 表映射:Code First 默认会按照类型名复数建立数据表,比如说Destination类对应的表名就叫Destinations;
  3. 列映射:Code First 默认会按照类中的属性名建立column,它还有默认的数据类型映射习惯,int会映射为interger,string会映射为 nvarchar(max),decimal会映射为decimal(18,2);
  4. 主键映射:Code First 默认会在类的属性中需找名字为Id或类型名称+Id的int类型的属性作为主键,并且是自增字段。

摘自这里
默认的映射一般只是简单的映射,当然这些都是可以修改的,请往下看。

II.使用Data Annotations和Fluent API配置数据库的映射

Data Annotations翻译过来就是数据注解,是通过直接在实体类的属性上加注类似标签的东西达到对数据库的映射;
Fluent API翻译过来就是流利的API,Fluent API是在DbContext中定义数据库配置的一种方式。要使用Fluent API 就必须在你自定义的继承自DbContext的类中重载OnModelCreating这个方法。
注意:使用Data Annotations必须添加引用:using System.ComponentModel.DataAnnotations; 更具体的引用请参考本章结尾的源码。

实战:
1.Data Annotations:
设置Destination表的Name不为null:

    [Required]
    public string Name { get; set; }

很简单,直接在属性上加[Required]标注即可;
2.Fluent API:
用Fluent api必须重写OnModelCreating方法,我们在上下文类里重写下OnModelCreating方法并添加不为空的配置:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<CodeFirst.Model.Destination>().Property(d => d.Name).IsRequired();
}

两种方式都可以配置EF对数据库的映射,任选其一就可以了。我更喜欢Fluent API的方式,故放出的demo中Data Annotations也是有的,不过都被注释了。随着开发的深入,有些东西还是必须用Fluent API的方式才能配置出来的。
上面的方法意思就是:先找到需要配置的实体类,然后点Property就是点出属性,=>是lambda表达式的写法,找到Name属性,然后调用IsRequired方法设置不为null。初见这东西肯定不好理解。没事,写法很固定,多写写就熟悉了。
注意:我的类库都修改了默认命名空间,都加了个CodeFirst. 方便区分,其他类库中调用,我也是习惯用完整的命名空间.类库再.实体类来调用。

思考:使用Fluent API方式配置,每次都需要在OnModelCreating方法里写上一行配置,这样一个实体类如果有3个属性需要配置,10个实体类就需要配置30个,那么就得在OnModelCreating方法里写30行,很麻烦且不易维护。

解决办法:注意返回值可以看出modelBuilder的Entity<>泛型方法的返回值是EntityTypeConfiguration<>泛型类。我们可以定义一个继承自EntityTypeConfiguration<>泛型类的类来定义domain中每个类的数据库配置。
ok,我们在DataAccess类库下新建一个继承自EntityTypeConfiguration<>泛型类的DestinationMap类,在构造函数里写上配置:

    public class DestinationMap : EntityTypeConfiguration<CodeFirst.Model.Destination>
{
public DestinationMap()
{
Property(d => d.Name).IsRequired();
}
}

需要添加引用:using System.Data.Entity.ModelConfiguration;
这样,以后Destination需要配置的都来这里配置,然后添加到上下文中的OnModelCreating方法即可:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DestinationMap());
}

其他类的配置也是这样,先添加一个类名+Map的方法(命名随意),然后添加到OnModelCreating方法。
随意配置一些属性,然后跑下程序看生成的数据库:

可见:Name列已经不可空,Description也设置了长度不超过500等等。
注意:如果重新跑程序生成数据库报这个错:
The model backing the 'BreakAwayContext' context has changed since the
database was created. Either manually delete/update the database, or
call Database.SetInitializer with an IDatabaseInitializer instance. For
example, the DropCreateDatabaseIfModelChanges strategy will
automatically delete and recreate the database, and optionally seed it
with new data.
意思就是,当前数据库正在使用中,无法删除再重新生成。这个时候断开数据库连接,再跑下程序就可以了。以后每次配置实体类再重新跑程序都需要断开数据库连接。

不知道大家还记不记得第一篇文章讲的EdmMetadata这个表,EF会自动帮我们生成这个表。这个表是监控实体类变化的,其实是个诟病,每次操作数据库都会发访问这张表的sql到数据库,用sql Profiler跟踪下即可发现如下sql:

2013.08.07补充:感谢园长dudu在回复中(4楼)的纠正,不是每次操作数据库都会发送sql到数据库,只是在EF初始化的时候会发送访问EdmMetadata表的sql到数据库。另推荐dudu的两篇文章供大家阅读:

  1. 让Entity Framework不再私闯sys.databases
  2. 揭开Entity Framework LINQ查询的一点面纱
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[ModelHash] AS [ModelHash]
FROM [dbo].[EdmMetadata] AS [Extent1]
ORDER BY [Extent1].[Id] DESC

补充:sql Profiler是一个监控发送到数据库sql语句的工具。sql server 2008自带,操作简单,如果不会请自行搜索相关资料。如果没有这个工具,那么是数据库版本不对或者数据库装出了问题。sql Profiler这工具后面讲一对一、一对多、多对多的各种操作时会经常使用到,也是我们调试EF语句性能的好帮手:

扩展:我们可以在OnModelCreating方法里添加:

modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//移除复数表名的契约
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();//防止黑幕交易 要不然每次都要访问

同样需要引入新的命名空间:

using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.Entity.Infrastructure;

第一句是移除复数表名的契约,就是EF默认生成的表名都是实体类的复数形式,有这句,表名就是实体类的名字了,不会再加个s了,当然你也可以通过强大的Fluent API配置这个。
第二句就是移除对EdmMetadata表的访问的,下次再操作数据库,就不会有访问EdmMetadata表的sql了。

注意:如果之前已经有数据库了,那么再加上移除对EdmMetadata表访问的配置再跑程序会报一个NotSupportedException的错:
Model compatibility cannot be checked because the EdmMetadata type was
not included in the model. Ensure that IncludeMetadataConvention has
been added to the DbModelBuilder conventions.
这个时候,我们先把BreakAwayConfigFile数据库分离,然后必须在本地删除掉,再跑程序就可以了。如果不知道sql server的mdf和ldf文件的默认路径,请自行搜索。
结果跑了下程序,的确没有产生对EdmMetadata表访问的sql了,但是sql
Profiler监控到了更多的sql语句被发送到了数据库。当初为了少一个访问EdmMetadata表的sql,结果多了更多的sql,并且如果再次生成数据库还必须要手动分离现有数据库并删除硬盘上的数据库文件。这里使不使用还是有待商量的,暂时注释掉:

//modelBuilder.Conventions.Remove<IncludeMetadataConvention>();

思考:EF小组设计EdmMetadata表肯定有它的道理,移除对其的访问也不一定是科学的。这里仅做学习演示,真正的项目中可能也很少用Code First的方式生成数据库的。至少4.1版本下的EF使用Code First是有缺陷的,每次都会干掉所有数据,这个肯定不合适。后续的版本有数据迁徙的功能能解决这个,我们目前只是学习4.1这个经典的EF版本。
补充:实际开发中还是database First的方式比较主流。

上面只演示了简单的Data Annotations和Fluent API的一些简单配置,其实还有很多,下面列出部分常用,初学者应该都试着敲敲,然后对照着生成的数据库好好学习下如何配置:

部分摘自这里
现在看了可能会头大,仅做了解和方便后期查阅。后续讲一对一、一对多和多对多的关系时反复的手写Fluent API的时候就会很好理解了。

源码:点击下载

http://www.kwstu.com/ArticleView/guandebao_201382485812638

EF的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射的更多相关文章

  1. EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射

    I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库的主键.外键以及表名和字段的类型等,这就是EF里的默认映射.具体分为: 数据库映射:Code First ...

  2. EF——默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射 02 (转)

    EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射   I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库 ...

  3. EF——使用Data Annotations和Fluent API配置数据库的映射配置 02.01(转)

    要更改EF中的默认配置有两个方法,一个是用Data Annotations(在命名空间System.ComponentModel.DataAnnotations;),直接作用于类的属性上面;还有一个就 ...

  4. 使用 Fluent API 配置/映射属性和类型(摘自微软Data Access and Storage)

    使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...

  5. EF使用Fluent API配置映射关系

    定义一个继承自EntityTypeConfiguration<>泛型类的类来定义domain中每个类的数据库配置,在这个自定义类的构造函数中使用我们上次提到的那些方法配置数据库的映射. 映 ...

  6. 使用 Fluent API 配置/映射属性和类型

    使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...

  7. 10.翻译系列:EF 6中的Fluent API配置【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/fluent-api-in-code-first.aspx EF 6 Code-Firs ...

  8. 使用Fluent API 配置/映射属性和类型

    Code First约定-Fluent API配置 使用Fluent API 配置/映射属性和类型 简介 通常通过重写派生DbContext 上的OnModelCreating 方法来访问Code F ...

  9. EF CodeFirst方式 Fluent Api配置

    一.One-to-One Relationship[一对一关系] 两个表之间,只能由一个记录在另外一个表中.每一个主键的值,只能关联到另外一张表的一条或者零条记录.请记住,这个一对一的关系不是非常的普 ...

随机推荐

  1. APICloud Studio2新建应用报错和检出错误

    今天心血来潮,闲暇时间想做个移动应用app,听一哥们说APICloud开发app很方便,就查询了一下,看了之后简直就是热血沸腾,我感觉正是我一直要找的工具 信心满满的开始着手使用,看了一下介绍我选择了 ...

  2. 简单的纯js三级联动

    参考这个  日尼禾尔  二级联动 写了三级联动 <!DOCTYPE html> <html> <head> <meta charset="UTF-8 ...

  3. SQL语句将一个表的数据写入到另一个表中

    在日常的数据库运维过程中,有时候需要将Select查询出来的数据集写入到另一个数据表中,其中一种方式是通过存储过程循环写入数据,另一种简便的方式是直接使用Insert Into语句后面跟上Select ...

  4. 简单shellcode编写

    0x00 介绍 Shellcode 是指经过精心设计的一串指令,一旦注入正在运行的应用程序中即可运行,常用于栈和基于堆的溢出.术语Shellcode意思指的便是用于启动一个命令Shell的已编写好的可 ...

  5. XMind 8 Pro 破解

    1.补丁下载地址 链接:https://pan.baidu.com/s/146qcwkvOGCAneIXabSZSUA    提取码:wygs 2.安装 XMind 8 Pro, 运行 3. 去除检查 ...

  6. SharpZipLib压缩解压的使用

    项目中使用 Velocity 将模板和生成的动态内容(HTML.XML等)合并保存到redis数据库中,考虑到压缩的文件容量会比较小,方便传输而且存储所使用的空间也会比较小,所以要压缩一下,读取的时候 ...

  7. 写一函数,用来求表达式1+2+3+.....+n的值,并编写主函数

    Description 写一函数,用来求表达式1+2+3+.....+n的值,并编写主函数.n由键盘输入. Input 输入一个整数 Output 输出表达式的值 Sample Input 5 Sam ...

  8. JProfiler的详细使用介绍

    转:https://blog.csdn.net/huangjin0507/article/details/52452946 下载软件 官网地址:http://www.ej-technologies.c ...

  9. windows环境中JDK环境变量配置

    一.环境准备 Windows10 jdk-9.0.1 二.下载并安装JDK 到Java的官网下载JDK安装包,地址:http://www.oracle.com/technetwork/java/jav ...

  10. dataTable tab栏切换时错位解决办法

    做后台管理类网站肯定要写列表,首选dataTable,功能强大 最近在做一个tab栏切换时发现了一个很诡异的事情:表头错位了! 主要时因为当table被隐藏后,table的header宽度会计算错乱, ...