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

LINQ to SQL 繼承映射實戰:單一資料表對應多重實體類型

     編輯:關於.NET

當業務邏輯中存在繼承階層(如「產品」為基類,「書籍」與「其他商品」為衍生類),但資料庫僅有一張 Products 表時,LINQ to SQL 的 單一資料表繼承映射 可完美解決物件關聯阻抗不匹配。本文以圖書銷售系統為例,完整示範從資料庫設計、實體類別定義、繼承映射屬性設定,到資料操作的全流程。

資料庫設計

單一 Products 表包含所有欄位,關鍵欄位 TypeID 作為 判別器:

  • TypeID = '1':基類 Product
  • TypeID = '2':書籍 Book
  • TypeID = '3':其他商品 OtherProduct

實體類別與映射屬性

基類 Product

[Table(Name = "dbo.Products")]
[InheritanceMapping(Code = "1", Type = typeof(Product), IsDefault = true)]
[InheritanceMapping(Code = "2", Type = typeof(Book))]
[InheritanceMapping(Code = "3", Type = typeof(OtherProduct))]
public partial class Product {
    [Column(IsPrimaryKey = true, DbType = "Int NOT NULL")] public int ProductID { get; set; }
    [Column(DbType = "VarChar(50)")] public string Name { get; set; }
    [Column(DbType = "Int")] public int? Stock { get; set; }
    [Column(DbType = "Decimal(18,2)")] public decimal? Price { get; set; }
    [Column(IsDiscriminator = true, Storage = "_TypeID", DbType = "VarChar(50)")] 
    public string TypeID { get; set; }
}

關鍵點:

  • InheritanceMapping 定義判別碼與類型對應
  • IsDiscriminator = true 標記 TypeID 為判別欄位
  • IsDefault = true 指定預設類型(資料庫中無法辨識的值將對應此類型)

衍生類別

public partial class Book : Product {
    [Column(DbType = "VarChar(50)")] public string ISBN { get; set; }
    [Column(DbType = "VarChar(50)")] public string Author { get; set; }
}

public partial class OtherProduct : Product {
    [Column(DbType = "VarChar(50)")] public string ProductFrom { get; set; }
}

衍生類別僅需定義專屬欄位,繼承基類共用欄位與主鍵。

資料上下文

public partial class MyDataContext : DataContext {
    public Table<Product> Products => GetTable<Product>();
    public MyDataContext(string connection) : base(connection, mappingSource) { }
    // 連線字串建構略...
}

建議:將實體類別與上下文從 .dbml 設計師分離,手動維護映射屬性,避免設計師覆寫自訂繼承設定。

實際操作範例

新增書籍

using (var dc = new MyDataContext(connStr)) {
    var book = new Book { ProductID = 1, Name = "C#", Price = 20, Stock = 100, Author = "lfm", ISBN = "123456" };
    dc.Products.InsertOnSubmit(book);
    dc.SubmitChanges();
}
// 產生 SQL: INSERT INTO Products (TypeID, ...) VALUES ('2', ...)

新增其他商品

var prod = new OtherProduct { ProductID = 2, Name = "C#", Price = 20, Stock = 100, ProductFrom = "bj" };
dc.Products.InsertOnSubmit(prod); // TypeID 自動填 '3'

查詢所有書籍

var books = from p in dc.Products where p is Book select p;
foreach (var b in books) Console.WriteLine(b.Name);

LINQ to SQL 會自動轉換為 WHERE TypeID = '2' 的 SQL。

優缺點與適用場景

優點缺點
單一表格,無 JOIN 查詢效能佳衍生類別專屬欄位在其他類型列為 NULL,浪費儲存空間
物件模型豐富,支援多型查詢資料庫端無法強制 NOT NULL 於衍生類別必填欄位
程式碼維護簡單,無需複雜映射設定不適用於衍生類別欄位極多或差異極大的情況

適合:繼承層級淺、共用欄位多、查詢效能敏感的案例。

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