EF Core 2.0中如何手动映射数据库的视图为实体

Posted opencoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 2.0中如何手动映射数据库的视图为实体的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core, Ef core : 在运行时动态映射存储库和服务

.net core EF Core 视图的应用

EF Core 5 - 如何将 EF.Functions.Like 与映射到 JSON 字符串的自定义属性一起使用?

ef core中如何实现多对多的表映射关系

EF Core中的多对多映射如何实现?

如何在 net-core 2.0 中手动解析 JSON 字符串