asp.net core系列 28 EF模型配置(欄位,構造函數,擁有實體類型)

来源:https://www.cnblogs.com/MrHSR/archive/2019/02/20/10405099.html
-Advertisement-
Play Games

一. 支持欄位 EF允許讀取或寫入欄位而不是一個屬性。在使用實體類時,用面向對象的封裝來限制或增強應用程式代碼對數據訪問的語義時,這可能很有用。無法使用數據註釋配置。除了約定,還可以使用Fluent API為屬性配置支持欄位。 1.1 約定 1.2 Fluent API 二. 構造函數 從開始 EF ...


一. 支持欄位

         EF允許讀取或寫入欄位而不是一個屬性。在使用實體類時,用面向對象的封裝來限制或增強應用程式代碼對數據訪問的語義時,這可能很有用。無法使用數據註釋配置。除了約定,還可以使用Fluent API為屬性配置支持欄位。

  1.1 約定

public class Blog
{
   // _<camel-cased property name>
    private string _url;

    public int BlogId { get; set; }

    public string Url
    {
        get { return _url; }
        set { _url = value; }
    }
}

  1.2 Fluent API

modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .HasField("_validatedUrl");

public class Blog
{
    private string _validatedUrl;
   
    public string Url
    {
        get { return _validatedUrl; }
    }

    public void SetUrl(string url)
    {
       //...
        _validatedUrl = url;
    }
}

 

二. 構造函數

  從開始 EF Core 2.1,可以定義帶參數的構造函數,併在創建實體實例時讓EF Core調用此構造函數。構造函數參數可以綁定到映射屬性,或綁定到各種服務,以方便延遲載入等行為。

  2.1  帶參的構造函數

    下麵代碼演示帶參數的構造函數,並且設置只讀屬性,外部調用該類時,只能通過構造函數傳入實體值。

public class Blog
{
    public Blog(int id, string name, string author)
    {
        Id = id;
        Name = name;
        Author = author;
    }

    public int Id { get; private set; }

    public string Name { get; private set; }
    public string Author { get; private set; }

    public ICollection<Post> Posts { get; } = new List<Post>();
}

    別外使用私有setter的另一種方法是使屬性真正只讀,併在OnModelCreating中添加更明確的映射。

public class Blog
{
    private int _id;

    public Blog(string name, string author)
    {
        Name = name;
        Author = author;
    }

    public string Name { get; }
    public string Author { get; }

    public ICollection<Post> Posts { get; } = new List<Post>();
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>(
        b =>
        {
            b.HasKey("_id");
            b.Property(e => e.Author);
            b.Property(e => e.Name);
        });
}

  

  2.2 註入服務

    EF Core還可以將“服務”註入實體類型的構造函數中。例如,可以註入以下內容:

           DbContext - 當前上下文實例,也可以作為派生的DbContext類型鍵入

           ILazyLoader- 延遲載入服務

           Action<object, string>- 一個延遲載入的委托

           IEntityType - 與此實體類型關聯的EF Core元數據

    例如,註入的DbContext可用於選擇性地訪問資料庫以獲得關於相關實體的信息而無需全部載入它們。在下麵的示例中,這用於獲取Blog博客中的Posts帖子數量:

public class Blog
{
    public Blog()
    {
    }

    private Blog(BloggingContext context)
    {
        Context = context;
    }

    private BloggingContext Context { get; set; }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Author { get; set; }

    public ICollection<Post> Posts { get; set; }

    //獲取帖子數量
    public int PostsCount
        => Posts?.Count
           ?? Context?.Set<Post>().Count(p => Id == EF.Property<int?>(p, "BlogId"))
           ?? 0;
}

     有一些需要註意:

           (1)構造函數是私有的,因為它只由EF Core調用,並且還有另一個通用的公共構造函數。

      (2)使用註入服務的代碼(即EF上下文)防禦它為null,處理EF Core未創建實例的情況。

      (3)因為服務存儲在讀或寫屬性中,所以當實體附加到新的上下文實例時,它將被重置。

    2.2示例演示,沒有成功,Blog帶參的構造函數為私有,無法調用, context上下文總為null,以後在瞭解。

 三.擁有的實體類型

   該功能是在 EF Core 2.0 中的新增功能。是指:當一個實體類中包含導航屬性(實體類型引用屬性),並對導航屬性進行建模,這個導航屬性類被稱為“擁有實體類型”。而包含“擁有實體類型”的類叫:所有者。

 

   3.1 顯示配置

     EF Core中的所有實體類型永遠不會按照約定包含在模型中。可以使用OwnsOne在(使用EF Core 2.1中的新增功能)OnModelCreating中使用或用註釋類型OwnedAttribute將類型配置為擁有類型。

     下麵示例中StreetAddress是一個沒有標識屬性的類型。 它用作 Order 類型的屬性來指定特定訂單的發貨地址。

//擁有實體類型
 [Owned]
public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

//所有者
public class Order
{
    public int Id { get; set; }

    public StreetAddress ShippingAddress { get; set; }
}

public class BloggingContext : DbContext
{
    public BloggingContext(DbContextOptions<BloggingContext> options)
            : base(options)
        { }
    public DbSet<Order> Order { get; set; }
}

    使用EF基於數據模型(Order)創建資料庫,如下圖所示。

        

    還可以使用該OwnsOne方法在OnModelCreating指定ShippingAddress屬性,是Order實體類型的擁有實體,並根據需要配置其他方面。

    modelBuilder.Entity<Order>().OwnsOne(p => p.ShippingAddress);

    如果ShippingAddress屬性在Order實體中為私有屬性,則可以使用的字元串版本OwnsOne方法:

    modelBuilder.Entity<Order>().OwnsOne(typeof(StreetAddress), "ShippingAddress");

 

  3.2 隱含鍵

    OwnsOne通過引用導航配置或發現的擁有類型始終與所有者具有一對一的關係,因此擁有實體不需要自己的鍵值,因為外鍵值是唯一的。在前面的示例中,StreetAddress類型不需要定義鍵屬性。擁有實體類型的實例鍵值與所有者實例的鍵值相同。

 

  3.3 擁有的集合類型

    要配置擁有的集合類型,使用OwnsManyOnModelCreating中使用。但是,主鍵不會按約定配置,因此需要明確指定。下麵代碼演示擁有的集合類型的關鍵代碼。

    public class Distributor
    {
        public int Id { get; set; }
        public ICollection<StreetAddress> ShippingCenters { get; set; }
    }


   modelBuilder.Entity<Distributor>().OwnsMany(p => p.ShippingCenters, a =>
            {
                // 給ShippingCenters表設置一個主鍵
                a.Property<int>("Id");
                //給ShippingCenters表設置一個外鍵
                a.HasForeignKey("DistributorId");
                //設置複合主鍵
                a.HasKey("DistributorId", "Id");
            });

    使用EF基於數據模型(Distributor)創建資料庫,如下圖所示(一對多的關係)。Distributor_ShippingCenters表的ID為主鍵,DistributorId為外鍵。

    關於擁有的實體類型的更多介紹參考官方文檔,這裡不是介紹。關於“EF模型配置系列”的很多功能,都是基於code first模式。

 

  參考文獻:

    官方文檔:EF支持欄位

           EF構造函數

           EF擁有的實體類型

           擁有實體類型的完整案例

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [toc] 函數定義 函數定義與變數定義相似, 函數示例 小結 函數用關鍵字 func 定義。 定義函數時, 函數名在前,返回類型在後 。 一個函數可以有 多個返回值 。 返回值可以指定一個名字(僅用於非常簡單的函數 )。 函數可以 作為參數 。 Go語言中函數 沒有預設參數、可選參數,函數重載 ...
  • 某些類的邏輯非常複雜,簡化代碼幫助理解下邏輯 ...
  • docker在windows下發力的時候必將取代各種虛擬機,並改變程式員的開發習慣,或許還會改變infra的工作。 概要: 在Windows下搭建開發環境一直是infra(我)頭疼的事情。為瞭解決這個問題,跟老闆,程式員商量得出的解決辦法有以下幾種:1.Mac下開發。優點是搭建環境方便,缺點是需要熟 ...
  • [toc] 條件語句 條件語句用 if 關鍵字來判定條件,如: for省略初始條件(及遞增條件), 相當於while語句 初始條件、結束條件、遞增表達式都省略是是一個死迴圈 Go中沒有while語句 ...
  • 現在好些網站都支持掃碼登錄,感覺上安全了很多,但是本地程式掃碼登錄的不多,就用C 實現了一下,需要作如下準備 1. 在官網上申請一個企業微信,有條件的話做個企業認證吧,我們的是認證過的,所以賬號和本地其他系統的賬號是統一的. 2. 在應用中創建一個應用,這個是關鍵,我們掃碼就是和它有關. 3. 點擊 ...
  • 0 綜述 1 MVP各模塊規範 1.1 實體模塊規範 1.1.1 命名規範 實體類封裝到單獨的DLL中,DLL命名遵循<ProjectName>.DataEntity。資料庫實體類名遵循:資料庫表名去掉複數尾碼,如“s”、“es”等(資料庫表的名稱必須是名詞複數)。 1.1.2 架構規範 實體模塊中 ...
  • 成功的故事固然蕩氣迴腸,失敗的故事也能千迴百轉,但是如果你連第一步都不願邁出,不去追求與償試,那麼你永完不會知道成功或者失敗的原因是什麼,人生一輩子也就三萬多天,如果每天糊裡糊塗的過去了,若幹年後可能連故事都沒得講。 年前的時候廣州.net俱樂部主席葉老師就曾微信找我私聊,說你可以在合肥組織一個合肥 ...
  • ASP.net core 使用UEditor.Core 實現 ueditor 上傳功能 首先通過nuget 引用UEditor.Core,作者github:https://github.com/baiyunchen/UEditor.Core/ 在Startup.cs中添加 引入ueditor並配置 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...