一、什么是视图

视图在RDBMS(关系型数据库管理系统)中扮演了一个重要的角色,它是将多个表的数据联结成一种看起来像是一张表的结构,但是没有提供持久化。因此,可以将视图看成是一个原生表数据顶层的一个抽象。例如,我们可以使用视图提供不同安全的级别,也可以简化必须编写的查询,尤其是我们可以在代码中的多个地方频繁地访问使用视图定义的数据。EF Code First模式现在还不完全支持视图,因此我们必须使用一种变通的方法。这种方法是:将视图真正看成是一张表,让EF定义这张表,然后在删除它,最后再创建一个代替它的视图。

二、使用EF的Code First模式管理视图

以图书和图书类型为例讲解如何使用EF的Code First模式管理视图。

1、创建实体类

BookType实体类定义如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CodeFirstViewApp.Model
{
public class BookType
{
public BookType()
{
Books = new HashSet<Book>();
} public int BookTypeId { get; set; } public string BookTypeName { get; set; } public virtual ICollection<Book> Books { get; set; }
}
}

Book实体类定义如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CodeFirstViewApp.Model
{
public class Book
{
public int Id { get; set; } public string Name { get; set; } public string Author { get; set; } public DateTime PublicationDate { get; set; } public virtual BookType BookType { get; set; }
}
}

2、创建模拟视图类

从多个实体中取出想要的列组合成一个实体,BookView模拟视图类定义如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CodeFirstViewApp.Model
{
public class BookView
{
public int BookId { get; set; } public string BookName { get; set; } public string Author { get; set; } public DateTime PublicationDate { get; set; } public string BookTypeName { get; set; }
}
}

3、为模拟视图类创建配置伙伴类

下面的代码指定了表名和主键。

注意:表名也是视图的名字,这里的表名一定要和创建视图的语句中的视图名一致。

 using CodeFirstViewApp.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CodeFirstViewApp.Map
{
/// <summary>
/// 定义配置伙伴类
/// </summary>
public class BookViewMap : EntityTypeConfiguration<BookView>
{
public BookViewMap()
{
// 设置表名
this.ToTable("BookViews");
// 设置主键
HasKey(p => p.BookId);
}
}
}

4、创建种子数据初始化器类

 using CodeFirstViewApp.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CodeFirstViewApp.EF
{
public class Initializer :DropCreateDatabaseAlways<EFDbContext>
{
/// <summary>
/// 重新Seed方法
/// </summary>
/// <param name="context"></param>
protected override void Seed(EFDbContext context)
{
// 创建初始化数据
BookType bookType = new BookType()
{
BookTypeName = "文学小说",
Books = new List<Book>
{
new Book(){Name="人间失格",Author="太宰治",PublicationDate=DateTime.Parse("2015-08-01")},
new Book(){Name="解忧杂货店",Author="东野圭吾",PublicationDate=DateTime.Parse("2014-05-01")},
new Book(){Name="追风筝的人",Author="卡勒德胡赛尼",PublicationDate=DateTime.Parse("2006-08-01")},
new Book(){Name="百年孤独",Author="加西亚马尔克斯",PublicationDate=DateTime.Parse("2011-06-01")},
new Book(){Name="霍乱时期的爱情",Author="加西亚马尔克斯",PublicationDate=DateTime.Parse("2015-06-01")}
}
}; BookType bookType2 = new BookType()
{
BookTypeName = "科学",
Books = new List<Book>
{
new Book(){Name="人类简史",Author="尤瓦尔赫拉利",PublicationDate=DateTime.Parse("2017-01-01")}
}
}; context.BookTypes.Add(bookType);
context.BookTypes.Add(bookType2); // 先删除表
var drop = "Drop Table BookViews";
context.Database.ExecuteSqlCommand(drop); // 创建视图
var createView = @"CREATE VIEW [dbo].[BookViews]
AS SELECT
dbo.Books.Id AS BookId,
dbo.Books.Name AS BookName,
dbo.Books.Author AS Author,
dbo.Books.PublicationDate AS PublicationDate,
dbo.BookTypes.BookTypeName AS BookTypeName
FROM dbo.Books
INNER JOIN dbo.BookTypes ON dbo.BookTypes.BookTypeId=dbo.Books.BookTypeId";
context.Database.ExecuteSqlCommand(createView);
base.Seed(context);
}
}
}

上面的代码中,我们先使用Database对象的ExecuteSqlCommand()方法销毁生成的表,然后又调用该方法创建我们需要的视图。该方法在允许开发者对后端执行任意的SQL代码时很有用。

5、创建数据上下文类

把实体类添加到数据上下文中,并配置实体之间的关系

 using CodeFirstViewApp.Map;
using CodeFirstViewApp.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CodeFirstViewApp.EF
{
public class EFDbContext:DbContext
{
public EFDbContext()
: base("name=AppConnection")
{
Database.SetInitializer(new Initializer());
} // 添加到数据上下文中
public DbSet<Book> Books { get; set; } public DbSet<BookType> BookTypes { get; set; } public DbSet<BookView> BookViews { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// 配置表名和主键
modelBuilder.Entity<Book>().ToTable("Books").HasKey(p => p.Id);
modelBuilder.Entity<BookType>().ToTable("BookTypes").HasKey(p => p.BookTypeId);
// 设置实体关系
// BookType和 Books 一对多关系 外键:BookTypeId
modelBuilder.Entity<BookType>().HasMany(p => p.Books).WithRequired(t => t.BookType)
.Map(m =>
{
m.MapKey("BookTypeId");
}); // 添加配置伙伴类
modelBuilder.Configurations.Add(new BookViewMap());
base.OnModelCreating(modelBuilder);
}
}
}

6、运行程序

Main()方法定义如下:

 using CodeFirstViewApp.EF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace CodeFirstViewApp
{
class Program
{
static void Main(string[] args)
{
using (var context = new EFDbContext())
{
// 获取视图的数据
var bookView = context.BookViews; // 循环遍历
bookView.ToList().ForEach(p =>
{
Console.WriteLine("Id:" + p.BookId + ",Name:" + p.BookName + ",BookTypeName;" + p.BookTypeName + ",PublicationDate:" + p.PublicationDate);
});
} Console.ReadKey();
}
}
}

运行程序,就会看到数据库中已经生成了Books和BookTypes两张表和BookViews视图,见下图:

运行结果如下图:

直接在数据库中查询视图:

注意:访问视图和任意数据表在代码层面没有任何区别,需要注意的地方就是在Seed()方法中定义的视图名称要和定义的表名一致,否则就会因为找不到表对象而报错。

示例代码下载地址:https://pan.baidu.com/s/1gf2FzDD

Entity Framework应用:使用Code First模式管理视图的更多相关文章

  1. Entity Framework应用:Code First模式数据迁移的基本用法

    使用Entity Framework的Code First模式在进行数据迁移的时候会遇到一些问题,熟记一些常用的命令很重要,下面整理出了数据迁移时常用的一些命令. 一.模型设计 EF默认使用id字段作 ...

  2. 学习Entity Framework 中的Code First

    这是上周就写好的文章,是在公司浩哥的建议下写的,本来是部门里面分享求创新用的,这里贴出来分享给大家. 最近在对MVC的学习过程中,接触到了Code First这种新的设计模式,感觉很新颖,并且也体验到 ...

  3. 转载:学习Entity Framework 中的Code First

    看完觉得不错,适合作为学习资料,就转载过来了 原文链接:http://www.cnblogs.com/Wayou/archive/2012/09/20/EF_CodeFirst.html 这是上周就写 ...

  4. Entity Framework 6.x Code Frist For Oracle 实践与注意点

    Entity Framework 6.x Code Frist For Oracle 实践与注意点 开发环境 Visual Studio.net 2015/2017 Oracle 11g/12c 数据 ...

  5. Entity Framework工具POCO Code First Generator的使用

    在使用Entity Framework过程中,有时需要借助工具生成Code First的代码,而Entity Framework Reverse POCO Code First Generator是一 ...

  6. Entity Framework工具POCO Code First Generator的使用(参考链接:https://github.com/sjh37/EntityFramework-Reverse-POCO-Code-First-Generator)

    在使用Entity Framework过程中,有时需要借助工具生成Code First的代码,而Entity Framework Reverse POCO Code First Generator是一 ...

  7. Entity Framework应用:Code First的实体继承模式

    Entity Framework的Code First模式有三种实体继承模式 1.Table per Type (TPT)继承 2.Table per Class Hierarchy(TPH)继承 3 ...

  8. Entity Framework 6.0 Code First(转)

    源自:http://www.cnblogs.com/panchunting/tag/Code%20First/ 1 Conventions 2 Custom Conventions 3 Data An ...

  9. Entity Framework 5.0 Code First全面学习

    摘自:http://blog.csdn.net/gentle_wolf/article/details/14004345 不贴图片了,太累. Code First 约定 借助 CodeFirst,可通 ...

随机推荐

  1. 跳出框架iframe的操作语句

    常用的iframe操作语句 ①   本页面跳转语句: "window.location.href" 或者 "location.href" ②   上一层页面跳转 ...

  2. Python学习笔记015——文件file的常规操作之三(标准输入输出文件)

    1 标准输入输出文件 在Python中,模块sys中含有标准的输入输出文件 sys.stdin     标准输入方法(一般是键盘) sys.stdout   标准输出方法(到显示器的缓冲输出) sys ...

  3. 转 python 读取中文文件名/中文路径

    python直接读取中文路径的文件时失败,可做如下处理: inpath = 'D:/work/yuanxx/在线导航/驾车导航/walk_log/20130619_172355.txt' uipath ...

  4. 进程控制块PCB结构 task_struct 描述

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

  5. Fix-Mapped Addresses

    一.前言 某天,wowo同学突然来了一句:如果要在start_kernel中点LED,ioremap在什么时间点才能调用呢?我想他应该是想通过点LED灯来调试start_kernel之后的初始化的代码 ...

  6. Python 列表 remove() 方法

    描述 Python 列表 remove() 方法通过指定元素的值来移除列表中某个元素的第一个匹配项,如果这个元素不在列表中会报一个异常. 语法 remove() 方法语法: L.remove(obj) ...

  7. 【服务器防护】linux 如何查看防火墙是否开启

    service iptables status可以查看到iptables服务的当前状态.但是即使服务运行了,防火墙也不一定起作用,你还得看防火墙规则的设置 iptables -L在此说一下关于启动和关 ...

  8. WinForm窗体键盘事件,支持方向键和回车键

    /// <summary> /// 快捷键操作 /// </summary> protected override bool ProcessCmdKey(ref Message ...

  9. php 多进程解决代码常驻内存的问题php 多进程解决代码常驻内存的问题

    PHP不适合做常驻的SHELl进程,因为它没有专门的gc例程,也没有有效的内存管理途径. 如果用PHP做常驻SHELL,会经常被内存耗尽导致abort而unhappy. 而且,如果输入数据非法,而脚本 ...

  10. iptables清空链的规则

    建立iptables时,首先需要情况系统默认的规则(如果有),这样能够保证iptables按照自己的想法运行. iptables -F   //清空链规则,但不会情况子链,也不会清空表的默认策略 ip ...