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指令已經可以自動映射數據庫中的視圖為實體,所以就不需要采用本文所述的方法了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM