zoukankan      html  css  js  c++  java
  • EF Core 2.0中如何手动映射数据库的视图为实体

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

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

    CREATE VIEW [dbo].[V_Person]
    AS
    SELECT   ID, Code, Name, CreateTime, UpdateTime
    FROM      dbo.Person
    GO

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

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

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

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

    using System;
    
    namespace FFCoreView.Entities
    {
        /// <summary>
        /// 定义实体V_Person,其结构和数据库视图V_Person相同
        /// </summary>
        public class V_Person
        {
            public int Id { get; set; }
            public string Code { get; set; }
            public string Name { get; set; }
            public DateTime? CreateTime { get; set; }
            public DateTime? UpdateTime { get; set; }
        }
    }

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

    using FFCoreView.Entities;
    using Microsoft.EntityFrameworkCore;
    
    namespace FFCoreView.Extension
    {
        /// <summary>
        /// TestDbExContext继承TestDBContext,而TestDBContext又继承DbContext
        /// </summary>
        public class TestDbExContext : TestDBContext
        {
            /// <summary>
            /// 定义一个DbSet<V_Person>的集合属性V_Person,EF Core会自动为其赋值,然后可以利用TestDbExContext.V_Person属性来读取数据库中V_Person视图的数据
            /// </summary>
            public virtual DbSet<V_Person> V_Person { get; set; }
    
            /// <summary>
            /// 在重写的OnModelCreating方法中,使用Fluent API来设置实体V_Person和数据库中V_Person视图的关系
            /// </summary>
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                //先调用基类的OnModelCreating方法,设置数据库中其它表和实体的映射关系
                base.OnModelCreating(modelBuilder);
    
                //接着设置实体V_Person和数据库中V_Person视图的关系
                modelBuilder.Entity<V_Person>(entity =>
                {
                    //告诉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会报错
                    entity.ToTable("V_Person");
    
                    //设置实体的唯一属性,因为我们知道数据库中V_Person视图的ID列值是唯一的,所以这里我们设置实体V_Person的Id属性为唯一属性
                    entity.HasKey(e => e.Id);
    
                    //利用Fluent API将实体V_Person的每一列映射到数据库视图的每一列
                    entity.Property(e => e.Id).HasColumnName("ID");
                    entity.Property(e => e.Code).HasColumnName("Code");
                    entity.Property(e => e.Name).HasColumnName("Name");
                    entity.Property(e => e.CreateTime).HasColumnName("CreateTime");
                    entity.Property(e => e.UpdateTime).HasColumnName("UpdateTime");
                });
            }
        }
    }

    在我们自定义的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:

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

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

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

  • 相关阅读:
    tomcat解压版环境变量配置
    十天冲刺(第二阶段)
    十天冲刺(第二阶段)
    十天冲刺
    十天冲刺第二阶段()
    十天冲刺(第二阶段)
    十天冲刺(第二阶段)
    十天冲刺(第一阶段)
    十天冲刺(第一阶段)
    十天冲刺(第一阶段)
  • 原文地址:https://www.cnblogs.com/OpenCoder/p/9807129.html
Copyright © 2011-2022 走看看