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

掌握 LINQ to SQL 核心:DataContext 與實體類別完整指南

     編輯:關於.NET

前言

DataContext 是 LINQ to SQL 的核心樞紐,負責查詢轉譯、物件追蹤、變更提交、交易管理與日誌記錄。本文將從手動定義實體、強型別 DataContext、日誌功能、查詢探究、原生 SQL 執行、資料庫建立/刪除、DbDataReader 整合等七大面向,全方位解析 DataContext 的實戰用法。

一、手動定義實體類別與對應屬性

[Table(Name = "Customers")]
public class Customer
{
    [Column(IsPrimaryKey = true)]
    public string CustomerID { get; set; }

    [Column(Name = "ContactName")]
    public string Name { get; set; }

    [Column]
    public string City { get; set; }
}
  • TableAttribute:指定資料表名稱
  • ColumnAttribute:`IsPrimaryKey`、`Name`(對應不同欄位名)、`DbType`、`CanBeNull` 等
  • 若未指定 `Name`,預設以屬性名對應欄位名

二、基本 DataContext 操作流程

using (var ctx = new DataContext(connStr))
{
    Table<Customer> customers = ctx.GetTable<Customer>();
    var q = from c in customers
            where c.CustomerID.StartsWith("A")
            select new { 顧客ID = c.CustomerID, 顧客名 = c.Name, 城市 = c.City };
    GridView1.DataSource = q;
    GridView1.DataBind();
}

連線字串可直接傳字串或 `IDbConnection`(如 `SqlConnection`)。

三、強型別 DataContext:更優雅的存取方式

public partial class NorthwindDataContext : DataContext
{
    public Table<Customer> Customers;
    public NorthwindDataContext(string connection) : base(connection) { }
    public NorthwindDataContext(IDbConnection connection) : base(connection) { }
}

// 使用
var ctx = new NorthwindDataContext(connStr);
var q = from c in ctx.Customers where c.CustomerID.StartsWith("A") select c;
  • IntelliSense 直接提示 `ctx.Customers`
  • 避免 `GetTable<T>()` 的字串錯誤風險
  • partial class 便於擴充自訂方法

四、日誌功能:除錯與效能分析利器

var ctx = new NorthwindDataContext(connStr);
var sw = new StreamWriter(Server.MapPath("log.txt"), true); // 附加模式
ctx.Log = sw;

var q = from c in ctx.Customers where c.CustomerID.StartsWith("A") select c;
GridView1.DataSource = q; GridView1.DataBind();

sw.Close();

log.txt 範例:

SELECT [t0].[CustomerID], [t0].[ContactName], [t0].[City]
FROM [Customers] AS [t0]
WHERE [t0].[CustomerID] LIKE @p0
-- @p0: Input String (Size = 2; Prec = 0; Scale = 0) [A%]
-- Context: SqlProvider(Sql2005) Model : AttributedMetaModel Build: 3.5.20706.1
  • 自動參數化、顯示參數型別與值
  • 附加模式適合長期監控

五、探究查詢:取得 DbCommand 與變更集

var q = from c in ctx.Customers where c.CustomerID.StartsWith("A") select c;
DbCommand cmd = ctx.GetCommand(q);
Response.Write(cmd.CommandText);
foreach (DbParameter p in cmd.Parameters)
    Response.Write($"參數名:{p.ParameterName}, 值:{p.Value}");

// 追蹤變更
var cust = ctx.Customers.First();
cust.Name = "zhuye";
var modified = ctx.GetChangeSet().ModifiedEntities;
Response.Write(((Customer)modified[0]).Name);
  • `GetCommand`:取得完整參數化命令,可離線分析
  • `GetChangeSet`:`Inserts`、`Updates`、`Deletes`、`ModifiedEntities` 四大集合

六、執行原生 SQL:彈性補足 LINQ 不足

// 更新
ctx.ExecuteCommand("UPDATE Customers SET City={0} WHERE CustomerID LIKE 'A%'", "Shanghai");

// 查詢對應實體
IEnumerable<Customer> list = ctx.ExecuteQuery<Customer>(
    "SELECT * FROM Customers WHERE CustomerID LIKE 'A%'");
GridView1.DataSource = list; GridView1.DataBind();
  • `ExecuteCommand`:回傳影響列數
  • `ExecuteQuery<T>`:將 DataReader 物質化為實體,支援延遲載入
  • 參數化語法 `{0}`、`{1}` 自動防注入

執行原生 SQL 結果

七、建立/刪除資料庫:Code-First 雛形

[Table(Name = "test")]
public class TestEntity
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int ID { get; set; }
    [Column(DbType = "varchar(20)")]
    public string Name { get; set; }
}

public partial class TestContext : DataContext
{
    public Table<TestEntity> Tests;
    public TestContext(string conn) : base(conn) { }
}

// 使用
var ctx = new TestContext("server=xxx;database=testdb;uid=xxx;pwd=xxx");
ctx.CreateDatabase();  // 依實體定義建立資料庫與資料表
// ctx.DeleteDatabase(); // 刪除

產生 DDL 相當於:

CREATE TABLE [dbo].[test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](20) NULL,
    CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED ([ID] ASC)
)

八、整合 DbDataReader:極致效能選項

using (var conn = new SqlConnection(connStr))
using (var ctx = new DataContext(conn))
{
    var cmd = new SqlCommand("SELECT * FROM Customers WHERE CustomerID LIKE 'A%'", conn);
    conn.Open();
    using (var reader = cmd.ExecuteReader())
    {
        GridView1.DataSource = ctx.Translate<Customer>(reader);
        GridView1.DataBind();
    }
}
  • `Translate<T>` 將 DataReader 直接映射為實體,避免 LINQ 查詢轉譯開銷
  • 適用於大量唯讀報表、高併發場景

九、總結與展望

功能關鍵 API適用場景
查詢轉譯LINQ 語法 / GetCommand標準 CRUD、強型別優勢
變更追蹤SubmitChanges / GetChangeSet樂觀平行存取、批次更新
日誌記錄Log 屬性除錯、效能調優、審計
原生 SQLExecuteCommand / ExecuteQuery複雜報表、大量資料操作、SP 呼叫
Schema 管理CreateDatabase / DeleteDatabase測試環境快速佈署、Code-First 原型
Reader 整合Translate<T>極致讀取效能、避免物質化開銷

下一篇將深入「查詢語法」進階篇,涵蓋 Join、GroupBy、分頁、集合運算等實戰技巧。

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