由于Scaffold-DbContext指令目前还不支持自动映射数据库中的视图为实体,所以当我们想使用EF Core来读取数据库视图数据的时候,我们需要手动去做映射,本文介绍如何在EF Core中手动映射数据库的视图为实体。

假设我们在SQL Server中有如下数据库视图[dbo].[V_Person]:

  1. CREATE VIEW [dbo].[V_Person]
  2. AS
  3. SELECT ID, Code, Name, CreateTime, UpdateTime
  4. FROM dbo.Person
  5. GO

其结构如下,共有五列数据:

在EF Core中映射数据库视图有一个硬条件,那就是视图中必须有一列要拥有唯一值,而如果你的视图中没有唯一列请在视图中构造一个唯一列(可以参考这个链接的文章)。这是因为EF Core要求每一个实体要拥有唯一属性(Key),而既然我们要把数据库视图映射为EF Core的实体,那么视图就要求必须有一个唯一列。

本例中数据库视图V_Person的列ID是唯一的。

首先我们定义一个实体类V_Person,用来映射数据库视图V_Person,其属性和数据库视图V_Person的列一一对应:

  1. using System;
  2.  
  3. namespace FFCoreView.Entities
  4. {
  5. /// <summary>
  6. /// 定义实体V_Person,其结构和数据库视图V_Person相同
  7. /// </summary>
  8. public class V_Person
  9. {
  10. public int Id { get; set; }
  11. public string Code { get; set; }
  12. public string Name { get; set; }
  13. public DateTime? CreateTime { get; set; }
  14. public DateTime? UpdateTime { get; set; }
  15. }
  16. }

然后我们来构造一个自定义的DbContext类TestDbExContext,其继承于Scaffold-DbContext指令自动生成的DbContext类TestDBContext:

  1. using FFCoreView.Entities;
  2. using Microsoft.EntityFrameworkCore;
  3.  
  4. namespace FFCoreView.Extension
  5. {
  6. /// <summary>
  7. /// TestDbExContext继承TestDBContext,而TestDBContext又继承DbContext
  8. /// </summary>
  9. public class TestDbExContext : TestDBContext
  10. {
  11. /// <summary>
  12. /// 定义一个DbSet<V_Person>的集合属性V_Person,EF Core会自动为其赋值,然后可以利用TestDbExContext.V_Person属性来读取数据库中V_Person视图的数据
  13. /// </summary>
  14. public virtual DbSet<V_Person> V_Person { get; set; }
  15.  
  16. /// <summary>
  17. /// 在重写的OnModelCreating方法中,使用Fluent API来设置实体V_Person和数据库中V_Person视图的关系
  18. /// </summary>
  19. protected override void OnModelCreating(ModelBuilder modelBuilder)
  20. {
  21. //先调用基类的OnModelCreating方法,设置数据库中其它表和实体的映射关系
  22. base.OnModelCreating(modelBuilder);
  23.  
  24. //接着设置实体V_Person和数据库中V_Person视图的关系
  25. modelBuilder.Entity<V_Person>(entity =>
  26. {
  27. //告诉EF Core实体V_Person对应数据库中的V_Person视图,这里使用entity.ToTable方法后,上面的DbSet<V_Person> V_Person集合属性可以叫任何名字,比如我们可以将其定义为DbSet<V_Person> V_People也可以,如果不使用entity.ToTable方法,那么DbSet<V_Person> V_Person的属性名字必须和数据库视图V_Person的名字相同,否则EF Core会报错
  28. entity.ToTable("V_Person");
  29.  
  30. //设置实体的唯一属性,因为我们知道数据库中V_Person视图的ID列值是唯一的,所以这里我们设置实体V_Person的Id属性为唯一属性
  31. entity.HasKey(e => e.Id);
  32.  
  33. //利用Fluent API将实体V_Person的每一列映射到数据库视图的每一列
  34. entity.Property(e => e.Id).HasColumnName("ID");
  35. entity.Property(e => e.Code).HasColumnName("Code");
  36. entity.Property(e => e.Name).HasColumnName("Name");
  37. entity.Property(e => e.CreateTime).HasColumnName("CreateTime");
  38. entity.Property(e => e.UpdateTime).HasColumnName("UpdateTime");
  39. });
  40. }
  41. }
  42. }

在我们自定义的TestDbExContext类中,我们定义了个DbSet<V_Person> V_Person集合属性,EF Core会为我们自动为其赋值,我们可以使用这个集合属性来读取数据库视图V_Person的所有数据,然后重写了DbContext的OnModelCreating方法,使用Fluent API来设置了实体V_Person和数据库中V_Person视图的关系。

然后我们在.NET Core控制台项目的Program类Main方法中,来使用自定义的TestDbExContext类读取视图V_Person的数据,注意加上AsNoTracking方法可以提高EF Core读取数据库视图数据的效率, 因为我们不会用实体来更改数据库视图的数据,所以可以用AsNoTracking方法来取消DbContext跟踪实体V_Person:

  1. using FFCoreView.Extension;
  2. using Microsoft.EntityFrameworkCore;
  3. using System;
  4. using System.Linq;
  5.  
  6. namespace FFCoreView
  7. {
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. using(TestDbExContext dbContext=new TestDbExContext())
  13. {
  14. var vPersons = dbContext.V_Person.AsNoTracking().ToList();//通过TestDbExContext.V_Person属性从数据库中查询视图数据,因为和数据库表不同,我们不会更新数据库视图的数据,所以调用AsNoTracking方法来告诉EF Core不用在DbContext中跟踪返回的V_Person实体,可以提高EF Core的运行效率
  15.  
  16. Console.WriteLine($"V_Person视图有{vPersons.Count.ToString()}行数据");
  17. }
  18.  
  19. Console.WriteLine("Press any key to quit...");
  20. Console.ReadKey();
  21. }
  22. }
  23. }

运行结果如下,我们成功读出了数据库视图V_Person的三行数据:

注意:
EF Core 3.0中Scaffold-DbContext指令已经可以自动映射数据库中的视图为实体,所以就不需要采用本文所述的方法了。

EF Core 2.0中如何手动映射数据库的视图为实体的更多相关文章

  1. EF Core 1.0中使用Include的小技巧

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:由于EF Core暂时不支持Lazy Loading,所以利用Include来加载额外 ...

  2. MySql 使用 EF Core 2.0 CodeFirst、DbFirst、数据库迁移(Migration)介绍及示例

    dotnet core 2.0 发布已经好几天了,期间也把原来 dotnet core 1.1 的 MVC 项目升级到了 2.0,升级过程还是比较顺利的,变动也不是太多.升级的过程中也少不了 Enti ...

  3. EF Core 2.0中Transaction事务会对DbContext底层创建和关闭数据库连接的行为有所影响

    数据库 我们先在SQL Server数据库中建立一个Book表: CREATE TABLE [dbo].[Book]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...

  4. EF Core 2.0中怎么用DB First通过数据库来生成实体

    要在EF Core使用DB First首先要下载三个Nuget包,在Nuget的Package Manager Console窗口中依次敲入下面三个命令即可: Microsoft.EntityFram ...

  5. EF Core 2.0 已经支持自动生成父子关系表的实体

    现在我们在SQL Server数据库中有Person表如下: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...

  6. EF Core 2.0 新特性

    前言 目前 EF Core 的最新版本为 2.0.0-priview1-final,所以本篇文章主要是针对此版本的一些说明. 注意:如果你要在Visual Studio 中使用 .NET Core 2 ...

  7. 【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  8. EF Core 2.0 执行原始查询如何防止SQL注入

    using (var context = new EFCoreDbContext()) { var searchString = "Jeffcky Wang"; Formattab ...

  9. [转]【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

随机推荐

  1. js for循环中点击事件中无法获取每一个i值的问题

    好像是第二次遇到这个问题,必须要总结一下!! <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...

  2. 20个实用便捷的CSS3工具、库及实例

    编者按:坊间传闻,有本CSS的高手炼成秘籍在江湖失传已久,书中所载,多为最新的惊人技术与实例示范,是为集大成者,一旦学成,代码效率猛增,功力提升数倍,今日偶获,不敢怠慢,赶紧发到优设,望人人受益.说人 ...

  3. drupal 开发笔记

    “以前我在开发Java项目的时候,都需要自己设计数据库表结构,数据库表结构的设计关系到一个人开发技能的高低,而在Drupal里面,我们通常是不需要设计数据库表结构,我们要做的是创建新的内容类型,然后为 ...

  4. Reporting Service 2005 迁移 到 2008

    1. 备份ReportServer 和ReportServerTempDB 的数据库. 2. 在Reporting Services Configuration Manager 中备份Encrypti ...

  5. LeetCode赛题391----Perfect Rectangle

    #391. Perfect Rectangle Given N axis-aligned rectangles where N > 0, determine if they all togeth ...

  6. 解决servlet在web.xml中的路径跳转问题

    <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" ...

  7. Android 解决NestedScrollView 嵌套 RecyclerView出现的卡顿,上拉刷新无效

    解决卡顿的方法最简单的就是设置RecyclerView的android:nestedScrollingEnabled="false",放弃自己的滑动,交给外部的NestedScro ...

  8. 使用 js 实现文本过多时隐藏部分文本

    使用 js 实现文本过多时隐藏部分文本 情景描述: 有时候我们需要显示部分文字,就像 QQ 空间这样,先显示部分文字,加一个[查看全文],让用户选择是否查看全部 解决方法: 第一步:在一个 id 为 ...

  9. 数值的整数次方(C++ 和 Python 实现)

    (说明:本博客中的题目.题目详细说明及参考代码均摘自 “何海涛<剑指Offer:名企面试官精讲典型编程题>2012年”) 题目 实现函数 double Power(double base, ...

  10. FTP作业

    实现一个FTP网盘的功能 pa's's