天天看點

asp.net core系列 23 EF 模型配置 (概述, 類型和屬性的包括與排除)

asp.net core系列 23 EF模型配置 (概述, 類型和屬性的包括與排除

一.模型配置概述

  EF使用一組約定基于實體類的定義來構模組化型。 可指定其他配置以補充或替代約定的内容。本系列介紹的配置可應用于面向任何資料存儲的模型,以及面向任意關系資料庫時可應用的配置。

  資料庫提供程式還可支援特定于具體資料存儲的配置,如Microsoft.EntityFrameworkCore.SqlServer,Pomelo.EntityFrameworkCore.MySql 等,對于特定配置的文檔參考資料庫提供程式。

  1.1 使用 fluent API 配置模型

    可在派生上下文中重寫 

OnModelCreating

 方法,并使用 

ModelBuilder API

 來配置模型。 此配置方法最為有效,并可在不修改實體類的情況下指定配置。 Fluent API 配置具有最高優先級,并将替代約定和資料注釋。下面示例指定Blog類型的Url在儲存時必填。如下所示:

class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>()
                .Property(b => b.Url)
                .IsRequired();
        }
    }      

  

  1.2 使用資料注釋來配置模型

    也可将特性(稱為資料注釋)應用于類和屬性。 資料注釋會替代約定,但會被 Fluent API 配置替代。下面示例指定Blog類型的Url在儲存時必填。如下所示:

public class Blog
    {
        public int BlogId { get; set; }

        [Required(ErrorMessage = "請輸入URL")]
        public string Url { get; set; }

        public ICollection<Post> Posts { get; set; }
    }      
[HttpPost]
     public async Task<IActionResult> Create([Bind("Url")] Blog blog)
      {
            if (ModelState.IsValid)
            {
                BloggingContext.Add<Blog>(blog);
                await BloggingContext.SaveChangesAsync();
            }
            return View();
      }      

    在MVC中, 新增一條Blog資料,Url 字段為空(包含空格),點選送出時,在背景Create中驗證,設定斷點檢視ModelState.IsValid為false。

    其中取Url字段的ErrorMessage資訊是:ModelState["URL"].Errors[0].ErrorMessage 

     

二.類型的包含和排除約定   

   将類型(實體類型)包含到模型中意味着,EF會有該類型的中繼資料,并且會嘗試從資料庫讀取執行個體(讀取對應的資料表),以及将執行個體(實體對象資料)寫入到資料庫中。按照約定,在上下文的 

DbSet

 屬性中公開的類型(實體類型)會包含在模型中。 此外,在 

OnModelCreating

 方法中提及的類型(實體類型)也将包含在其中。 最後,通過以遞歸方式浏覽已發現類型的導航屬性而找到的任何類型也會包含在模型中。下面舉例一 一說明:

  

  2.1  類型包含約定

class MyContext : DbContext
{
    //公開Blog類型,将與資料庫表産生映射關系 
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
       //公開AuditEntry類型,将與資料庫表産生映射關系
        modelBuilder.Entity<AuditEntry>();
    }
}

    public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    //公開Post類型,通過導航屬性。将與資料庫表産生映射關系
    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog { get; set; }
}

public class AuditEntry
{
    public int AuditEntryId { get; set; }
    public string Username { get; set; }
    public string Action { get; set; }
}      

    上面示例中:

(1)Blog

,因為它是在上下文的 

DbSet

 屬性中公開的。(2)

Post

,因為它是通過 

Blog.Posts

 導航屬性發現的。(3)

AuditEntry

,因為它在 

OnModelCreating

 中提及。

  2.2 類型排除約定

     (1)可以使用資料注釋來從模型中排除類型。

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public BlogMetadata Metadata { get; set; }
}

[NotMapped]
public class BlogMetadata
{
    public DateTime LoadedFromDatabase { get; set; }
}      

    (2)也可以通過Fluent API 把模型中類型排除。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Ignore<BlogMetadata>();
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public BlogMetadata Metadata { get; set; }
}

public class BlogMetadata
{
    public DateTime LoadedFromDatabase { get; set; }
}      

 三.屬性的包含和排除約定

   模型中包含屬性意味着 EF 擁有該屬性的中繼資料,并将嘗試從資料庫讀取值或者向資料庫寫入值。按照約定,模型所含的那些公共屬性都擁有一個 getter 和一個 setter。

  3.1 資料注釋

     可以使用資料注釋方式來從模型中排除某個屬性

public class Blog
    {
       //公開的屬性
        public int BlogId { get; set; }
        public string Url { get; set; }

       //排除的屬性
       [NotMapped]
        public DateTime LoadedFromDatabase { get; set; }
    }      

   3.2 Fluent API

     也可以用Fluent API 從模型中排除某個屬性。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>().Ignore(b => b.LoadedFromDatabase);
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public DateTime LoadedFromDatabase { get; set; }
}      

  參考文獻:

    官方資料:建立并配置模型

           包括和排除類型

           包括和排除屬性

  

posted on 2019-02-15 09:25 花陰偷移 閱讀(...) 評論(...) 編輯 收藏