首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

LINQ to SQL 繼承映射完整指南:單表策略與查詢模式

     編輯:關於.NET

LINQ to SQL 繼承映射概述

LINQ to SQL 採用單表映射策略實現繼承層次結構,將整個繼承體系的所有類別欄位平展儲存於單一資料表中。每一列代表層次結構中某個類別的屬性,不適用於該列所對應實例類型的欄位則設為 NULL。此策略結構簡單,且對多類別查詢具備優異效能。

實作繼承映射的關鍵步驟

若要在 LINQ to SQL 中實現單表繼承映射,必須在根類別上套用下列屬性與設定:

  1. 於根類別標記 [Table] 屬性。
  2. 為層次結構中每個類別新增 [InheritanceMapping] 屬性(同樣加在根類別上),指定 Code(鑑別器欄位的值)與 Type(對應的類別型別)。
  3. 在其中一個 [InheritanceMapping] 上設定 IsDefault = true,作為鑑別器值無匹配時的回退對應。
  4. 於鑑別器欄位(如 ContactType)加上 [Column(IsDiscriminator = true)]。

程式碼範例:Contact 繼承體系

以下為使用 O/R 設計器產生的核心程式碼架構(已簡化):

[Table(Name = "dbo.Contacts")]
[InheritanceMapping(Code = "Unknown", Type = typeof(Contact), IsDefault = true)]
[InheritanceMapping(Code = "Employee", Type = typeof(EmployeeContact))]
[InheritanceMapping(Code = "Supplier", Type = typeof(SupplierContact))]
[InheritanceMapping(Code = "Customer", Type = typeof(CustomerContact))]
[InheritanceMapping(Code = "Shipper", Type = typeof(ShipperContact))]
public partial class Contact : INotifyPropertyChanging, INotifyPropertyChanged
{
    [Column(Storage = "_ContactID", IsPrimaryKey = true, IsDbGenerated = true)]
    public int ContactID { get; set; }

    [Column(Storage = "_ContactType", IsDiscriminator = true)]
    public string ContactType { get; set; }
}

public abstract partial class FullContact : Contact { }
public partial class EmployeeContact : FullContact { }
public partial class SupplierContact : FullContact { }
public partial class CustomerContact : FullContact { }
public partial class ShipperContact : Contact { }

O/R 設計器繼承關係圖

常見查詢模式與生成的 SQL

1. 一般查詢(查詢所有聯繫人)

var cons = from c in db.Contacts select c;
foreach (var con in cons) {
    Console.WriteLine($"Company: {con.CompanyName}, Type: {con.GetType()}");
}

2. OfType<T> 篩選特定子類別

var cons = from c in db.Contacts.OfType<CustomerContact>() select c;

生成 SQL 會自動加上 WHERE ContactType = 'Customer'。

3. 使用 is 型別檢查

var cons = from c in db.Contacts where c is ShipperContact select c;

同樣轉譯為 WHERE ContactType = 'Shipper',但會選取資料表所有欄位。

4. as 轉型查詢

var cons = from c in db.Contacts select c as FullContact;

查詢整個 Contacts 表,不加 WHERE 條件。

5. Cast 強制轉型搭配條件

var cons = from c in db.Contacts
           where c.ContactType == "Customer" && ((CustomerContact)c).City == "London"
           select c;

生成 SQL 同時篩選 ContactType 與 City。

6. UseAsDefault 行為差異

插入新紀錄時若 ContactType 為 null,會套用 IsDefault = true 對應的基底類別(Contact);查詢時則依繼承映射邏輯解析。

7. 插入、查詢、刪除完整流程

// 插入 ShipperContact
ShipperContact nsc = new ShipperContact {
    CompanyName = "Northwind Shipper",
    Phone = "(123)-456-7890"
};
db.Contacts.InsertOnSubmit(nsc);
db.SubmitChanges();

// 查詢驗證
var ShipperContacts = from sc in db.Contacts.OfType<ShipperContact>()
                      where sc.CompanyName == "Northwind Shipper"
                      select sc;

// 刪除
db.Contacts.DeleteOnSubmit(nsc);
db.SubmitChanges();

對應 SQL 依序為 SELECT COUNT(*)、INSERT、SELECT COUNT(*)、DELETE,皆自動帶入鑑別器值 'Shipper'。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved