一、数据迁移
用来解决code first情况下当增加、删除、改变实体类,或改变DbContext类后,相应地更新数据库结构而不会对现有数据产生影响。

1、启用迁移
指令:
enable-migrations
add-migration XXX

enable-migrations指令:
a.在项目根目录下创建了一个Migrations文件夹
b.在Migrations文件夹下新建一个Configuration.cs文件。
可以通过修改Configuration.cs来对Migration做一些配置(如加入一些测试数据等)

类似初始化数据的AccountInitilizer.cs类,数据迁移的Configuration类也包含一个Seed方法。
当数据库新建或数据库结构更新后,这个方法会被调用,利用这个方法可以插入或更新test data。

2、配置Seed方法
使用drop and re-create的方式时,因为每次model改变时数据库都会被删除,所有数据都会丢失,所以需要使用DALàAccountInitilizer.cs的Seed方法来插入测试数据。
使用Code First Migrations方式,当数据库改变时测试数据会保留,所以包含test data的Seed方法一般来说是不需要的。
如果我们要部署数据库到生产环境,事实上这种情况下我们也不想Seed方法来插入测试数据到生产环境中。
但是,也有特殊情况, 比如在我们部署时获得了实际的初始化数据,如实际存在的组织部门这些初始化的信息,这时候就用到Seed方法。

与AccountInitilizer.cs类中Seed方法不同的是,以前都是用Add方法,这次用了AddOrUpdate方法来插入数据。如:
sysUsers.ForEach(s => context.SysUsers.AddOrUpdate(p => p.UserName, s));

3、执行迁移
指令:update-database

前面执行 add-migration时,同样在Migrations文件夹里面,产生一个<timestamp>_InitialCreate.cs的文件。
里面两个方法,Up和Down:
Up方法创建数据库表,Down方法删除表。

update-database指令调用了Up方法来新建database的表(和data model entity set对应), 然后调用Seed方法来填充测试数据。

数据迁移执行步骤:
1、enable-migrations(如已启用,则略过此步)
2、add-migration XXX
3、update-database

二、数据注解属性(DataAnnotations)
对某一些类型来说不需要使用Required, 例如DateTime, int,double,float,因为这些值类型不能被赋予空值,因此他们天生就具有Required的特性。

Column - 列名称
Required - not null
StringLength(20) - nvarchar(20)
TypeName - 改变SQL数据类型,如把double改成decimal

三、加载关联数据
EF有三种方式可以加载关联数据到一个实体的navigation属性中
Lazy loading(懒加载)
Eager loading(热加载)
Explicit loading(显式加载)

1、Lazy loading(懒加载)
第一次读取entity的时候不会加载。
当需要读取navigation property的时候,相关的数据将会被自动读取。
这种情况会导致多次查询数据库。
(这种加载方式是,默认不加载导航属性关联的数据,但是如果用到了,就加载。)
例如:
using (var context = new TestEntities())
{
    IQueryable<Team> teams = from t in context.Teams select t;
    foreach (Team t in teams)
    {
        Console.WriteLine(t.Players.Count());
    }
    Console.Read();
}
再如:

关闭懒加载方法:
(1)context.ContextOptions.LazyLoadingEnabled = false;
(2)EDMX文件属性LazyLoadingEnabled设置为False;
(3)对特定的navigation properties来说,省略property的virtual关键字就可以了(待确定);
导航属性加virtual修饰,为的是Entity Framework Code First的延迟加载功能(懒加载)。当然Entity Framework Code First延迟加载并不是必须的,所以virtual修饰符也可以不加。
优势和劣势:
当打开Lazy Loading时,我们可以不用去在意某实体是否已经加载,不会出现在调用某一实体时,出现null的尴尬,省去程序员不少心力,但同时劣势也非常明显,如果我们有大量实体,且频繁去调用相关实体,程序就会频繁地访问数据库,这很显然地会影响程序的性能。

2、Eager loading(贪婪加载)
当读取entity的时候,相关数据会被一起读取。
一般来说这种方式会产生一个join query来获取所有需要的数据。
通过Include方法来指定eager loading.
例如:
using (var context = new TestEntities())
{
    var players = from p in context.Players.Include("Team").Include("PlayerDetails") where (p.PlayerDetails.Any(d => d.Height > 200)) select p;
    foreach (var v in players)
    {
        string output = string.Format("Team: {0} Player: {1}", v.Team.TeamName, v.PlayerName);
         Console.WriteLine(output);
    }
    Console.Read();
}
再如:

3、Explicit loading(显式加载)
和lazy loading类似,除了需要在代码中明确指定需要获取的关联数据。
在读取navigation property时explicit loading 不会自动发生,你需要手动加载相关数据。
通过获取object
state manager entry for entity,调用Collection.Load method for
collections或者Reference.Load method for properties that hold a single
entity.
一般来说,只有在关闭lazying loading的时候才会使用explicit loading.
例如:
using (TestEntities context = new TestEntities())
{
     IQueryable<Player> players = from p in context.Players select p;
     foreach (Player p in players)
     {
         if (p.Age > 30)
         {
             p.TeamReference.Load();
             Console.WriteLine(p.PlayerName + " -> " + p.Team.TeamName);
         }                   
     }
     Console.Read();
}
再如:

总结:
1、lazy loading 和 explicit loading都不立即获取property values,它们也被称作deferred loading.
2、无论使用Lazy Loading还是将Load方法放入foreach循环语句(Explicit loading),都会导致程序频繁访问数据库,导致程序性能下降。我们可以选择性地加载需要的实体。

自己总结:
1、lazy loading 和 explicit loading都会有频繁访问数据库的性能问题;所以用Eager loading(贪婪加载)比较保险点;
2、Include(Eager loading)生成其实是用的left join进行表关联,并且select所有关联的表字段(包括ID)。
下面是两个生成的SQL示例:
示例1:
var user = from a in db.sysUsers.Include("SysUserRoles").Include("SysDepartment")
                       where a.ID == id
                       select a;
生成的SQL:
SELECT
[Project1].[ID] AS [ID],
[Project1].[UserName] AS [UserName],
[Project1].[Email] AS [Email],
[Project1].[PassWord] AS [PassWord],
[Project1].[CreateDate] AS [CreateDate],
[Project1].[SysDepartmentID] AS [SysDepartmentID],
[Project1].[ID1] AS [ID1],
[Project1].[DepartmentName] AS [DepartmentName],
[Project1].[DepartmentDesc] AS [DepartmentDesc],
[Project1].[C1] AS [C1],
[Project1].[ID2] AS [ID2],
[Project1].[SysUserID] AS [SysUserID],
[Project1].[SysRoleID] AS [SysRoleID]
FROM ( SELECT
    [Limit1].[ID] AS [ID],
    [Limit1].[UserName] AS [UserName],
    [Limit1].[Email] AS [Email],
    [Limit1].[PassWord] AS [PassWord],
    [Limit1].[CreateDate] AS [CreateDate],
    [Limit1].[SysDepartmentID] AS [SysDepartmentID],
    [Extent2].[ID] AS [ID1],
    [Extent2].[DepartmentName] AS [DepartmentName],
    [Extent2].[DepartmentDesc] AS [DepartmentDesc],
    [Extent3].[ID] AS [ID2],
    [Extent3].[SysUserID] AS [SysUserID],
    [Extent3].[SysRoleID] AS [SysRoleID],
    CASE WHEN ([Extent3].[ID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
   
FROM    (SELECT TOP (1) [Extent1].[ID] AS [ID], [Extent1].[UserName] AS
[UserName], [Extent1].[Email] AS [Email], [Extent1].[PassWord] AS
[PassWord], [Extent1].[CreateDate] AS [CreateDate],
[Extent1].[SysDepartmentID] AS [SysDepartmentID]
        FROM [dbo].[SysUser] AS [Extent1]
        WHERE [Extent1].[ID] = @p__linq__0 ) AS [Limit1]
    LEFT OUTER JOIN [dbo].[SysDepartment] AS [Extent2] ON [Limit1].[SysDepartmentID] = [Extent2].[ID]
    LEFT OUTER JOIN [dbo].[SysUserRole] AS [Extent3] ON [Limit1].[ID] = [Extent3].[SysUserID]
)  AS [Project1]
ORDER BY [Project1].[ID] ASC, [Project1].[ID1] ASC, [Project1].[C1] ASC

示例2:分页
var users = from u in db.sysUsers.Include("SysDepartment") select u;
return View(users.ToPagedList(pageNum,pageSize));

SELECT TOP (3)
[Join1].[ID1] AS [ID],
[Join1].[UserName] AS [UserName],
[Join1].[Email] AS [Email],
[Join1].[PassWord] AS [PassWord],
[Join1].[CreateDate] AS [CreateDate],
[Join1].[SysDepartmentID] AS [SysDepartmentID],
[Join1].[ID2] AS [ID1],
[Join1].[DepartmentName] AS [DepartmentName],
[Join1].[DepartmentDesc] AS [DepartmentDesc]
FROM
( SELECT [Extent1].[ID] AS [ID1], [Extent1].[UserName] AS [UserName],
[Extent1].[Email] AS [Email], [Extent1].[PassWord] AS [PassWord],
[Extent1].[CreateDate] AS [CreateDate], [Extent1].[SysDepartmentID] AS
[SysDepartmentID], [Extent2].[ID] AS [ID2], [Extent2].[DepartmentName]
AS [DepartmentName], [Extent2].[DepartmentDesc] AS [DepartmentDesc],
row_number() OVER (ORDER BY [Extent1].[UserName] ASC) AS [row_number]
    FROM  [dbo].[SysUser] AS [Extent1]
    LEFT OUTER JOIN [dbo].[SysDepartment] AS [Extent2] ON [Extent1].[SysDepartmentID] = [Extent2].[ID]
)  AS [Join1]
WHERE [Join1].[row_number] > 0
ORDER BY [Join1].[UserName] ASC

参考:
http://www.cnblogs.com/kevin2013/p/5239186.html
http://www.cnblogs.com/itjeff/p/4137733.html

MVC4学习要点记三的更多相关文章

  1. MVC4学习要点记四

    一.使用原生SQL使用EF的一个优点就是自动帮我们生成SQL,这在常规情况下很方便,但有些情况下用EF却不适合.另外还有些特别复杂的语句,利用EF很难生成.所以,EF提供一组方法用来执行原生的SQL. ...

  2. MVC4学习要点记二

    一.分页(PagedList.MVC)1.安装PagedList.MVCPM>install-package PagedList.mvc   2.控制器中使用PagedList   3.csht ...

  3. MVC4学习要点记一

    强类型的辅助方法:这些helper的特征是名称后面加上了 For , 这些叫做强类型的辅助方法. 共用布局页:可以在Views文件夹下面新建一个视图页,命名为_ViewStart.cshtml,将这部 ...

  4. 【C#】第3章学习要点(三)--常用类和结构的用法

    分类:C#.VS2015 创建日期:2016-06-19 使用教材:(十二五国家级规划教材)<C#程序设计及应用教程>(第3版) 一.DateTime结构和TimeSpan结构 DateT ...

  5. EntityFramework学习要点记一

    一.Entity的注解属性(Annotations)不管是code first还是db first,都需要用到注解属性,至于用System.ComponentModel.DataAnnotations ...

  6. Java Web编程技术学习要点及方向

    学习编程技术要点及方向亮点: 传统学习编程技术落后,应跟著潮流,要对业务聚焦处理.要Jar, 不要War:以小为主,以简为宝,集堆而成.去繁取简 Spring Boot,明日之春(future of ...

  7. 【C#】第3章学习要点(一)--整体把握

    分类:C#.VS2015 创建日期:2016-06-18 使用教材:(十二五国家级规划教材)<C#程序设计及应用教程>(第3版) 一.使用别人已经设计好的类简化你的代码编写工作量 当让你去 ...

  8. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  9. PyQt4入门学习笔记(三)

    # PyQt4入门学习笔记(三) PyQt4内的布局 布局方式是我们控制我们的GUI页面内各个控件的排放位置的.我们可以通过两种基本方式来控制: 1.绝对位置 2.layout类 绝对位置 这种方式要 ...

随机推荐

  1. QT .pro文件中的变量说明

      https://blog.csdn.net/tanou3212/article/details/79942840 TEMPLATE:定义了工程的编译模式 赋值方式为:TEMPLATE=app (1 ...

  2. 汽车辐射监测系统-Qt开发[转]发

    功能介绍: 利用在路边的两个探测器,探测汽车的辐射剂量,通过电子板进行数据采集,并串口传输到计算机,实时显示.可以保存采集数据,进行独立显示. 开发环境: VS2008,Qt4.7, QWT 6.0. ...

  3. ESXi 5.1 识别GPT问题

    使用paredUtil命令 partedUtil mklabel /dev/disks/eui.227c000155707e0b msdospartedUtil mklabel /dev/disks/ ...

  4. pytorch-LeNet网络

    LeNet网络的结构 输入的32x32x1的单通道图片, 第一层网络: 3x3x1x6的卷积层,步长为1, padding = 1, 经过2x2的池化操作 第二层网络: 5x5x6x16的卷积层, 步 ...

  5. 本地服务CURL请求本地另一个服务API返回超时/或无返回

    入职之后一直在忙,终于有时间整理一波最近踩到的坑. 起因: 项目是微服务架构,一个项目对外提供API,新的项目调用API获得数据.于是就在本地搭建了两个服务.配置了两个虚拟域名,指向两个项目,当然我本 ...

  6. parted对大容量磁盘进行分区

    Linux系统中MBR与GPT的区别 主引导记录(Master Boot Record , MBR)是指一个存储设备的开头 512 字节.它包含操作系统的引导器和存储设备的分区表. 全局唯一标识分区表 ...

  7. Ubuntu16.04.3安装并配置samba方法

    目的:单个Linux用户可以在windows电脑上通过映射网络驱动器的方式来访问自己的工作目录. 方法如下: 1.安装smb服务器:apt-get install samba2.安装smb支持的文件系 ...

  8. backupAgent节点

    在<application>节点中有一个非常重要的属性,那就是backupAgent. 1.backupAgent简介 Androidd:backupAgent用来设置备份代理.对于大部分 ...

  9. Selenium 2自动化测试实战34(编写Web测试用例)

    编写Web测试用例 1.介绍了unittest单元测试框架,其主要是来运行Web自动化测试脚本.简单的规划一下测试目录:web_demo1/------test_case/------------te ...

  10. python+Selenium PhantomJS网页截图

    PhantomJS是一个基于webkit的JavaScript API.它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JavaScript代码.任何你可以在基于webki ...