首頁 > 軟體

Entity Framework使用Code First模式管理檢視

2022-03-05 16:01:11

一、什麼是檢視

檢視在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()方法中定義的檢視名稱要和定義的表名一致,否則就會因為找不到表物件而報錯。

範例程式碼下載地址:點此下載

到此這篇關於Entity Framework使用Code First模式管理檢視的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com