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

ADO.NET Entity Framework 實戰筆記(五):Entity SQL 基礎語法與 ObjectQuery 操作全解析 (上)

     編輯:關於.NET

Entity Framework 除支援 LINQ to Entities 外,還提供功能強大的 Entity SQL (ESQL)——一種以字串為基礎、語法類 T-SQL 但面向概念模型 (EDM) 的查詢語言。本文系統整理 ESQL 的查詢結果型別、核心關鍵字、參數化查詢、中文欄位處理、CommandText/ToTraceString 除錯、ObjectQuery LINQ 風格擴充方法、註解/成員存取/分行、運算子、分頁與集合運算,並附帶對應生成的 T-SQL,助你快速上手並深入理解轉譯機制。

一、ESQL 查詢結果集:三種 ObjectQuery 型別

查詢形式關鍵字回傳型別適用場景
實體查詢SELECT VALUE entityObjectQuery<Entity>需完整實體物件、後續修改/追蹤
投影/標量查詢SELECT prop1, prop2ObjectQuery<DbDataRecord>僅需部分欄位、匿名記錄、彙總函數
單一值/標量SELECT VALUE scalarObjectQuery<PrimitiveType>COUNT、MAX、單一欄位值集合

// 1. ObjectQuery<Entity>
string esql = "SELECT VALUE it FROM ctx.DBItemList AS it";
var q1 = ctx.CreateQuery<DBItemList>(esql);
foreach (var r in q1) Console.WriteLine(r.NameID);

// 2. ObjectQuery<DbDataRecord>
esql = "SELECT it.NameID FROM ctx.DBItemList AS it";
var q2 = ctx.CreateQuery<DbDataRecord>(esql);
foreach (var r in q2) Console.WriteLine(r["NameID"]);

// 3. ObjectQuery<Int32> (標量)
esql = "SELECT VALUE COUNT(it.NameID) FROM ctx.DBItemList AS it";
var q3 = ctx.CreateQuery<int>(esql);
foreach (var n in q3) Console.WriteLine(n);

二、核心關鍵字與用法

1. it 關鍵字 (範圍變數)

預設別名為 it,可透過 ObjectQuery.Name 屬性自訂:


ctx.DBItemList.Name = "wxd";
var q = ctx.DBItemList.Where("wxd.ItemValue = 5"); // 使用自訂別名

2. VALUE 關鍵字

強制回傳單一值/實體,而非記錄結構:


// 回傳標量
esql = "SELECT VALUE AVG(it.ItemValue) FROM ctx.DBItemList AS it";
// 回傳實體
esql = "SELECT VALUE it FROM ctx.DBItemList AS it";
// 回傳建構的 ROW (仍為 DbDataRecord)
esql = "SELECT VALUE ROW(it.ItemValue, it.NameID, 'wxd' AS wxwinter) FROM ctx.DBItemList AS it";

3. 參數化查詢 (防止注入、計畫重用)


string esql = "SELECT VALUE it FROM ctx.DBItemList AS it WHERE it.ItemValue = @v1 OR it.NameID = @v2";
var p1 = new ObjectParameter("v1", 3);
var p2 = new ObjectParameter("v2", "n01");
var q = ctx.CreateQuery<DBItemList>(esql, p1, p2);

4. 中文欄位名稱處理

使用 [] 括住識別碼:


// 欄位名為「值」
var q = ctx.typeTest.Where("it.[值] == 22.22"); // 正確
// var q = ctx.typeTest.Where("it.值 == 22.22"); // 錯誤

中文欄位查詢結果

三、除錯利器:CommandText 與 ToTraceString


string esql = "SELECT VALUE it FROM ctx.DBItemList AS it";
var q = ctx.CreateQuery<DBItemList>(esql);

Console.WriteLine("【ESQL】" + q.CommandText);     // 原始 ESQL 字串
Console.WriteLine("【T-SQL】" + q.ToTraceString()); // 轉譯後的 T-SQL (需先 Open Connection)

輸出範例:


【ESQL】SELECT VALUE it FROM ctx.DBItemList AS it
【T-SQL】SELECT [Extent1].[AutoId] AS [AutoId], [Extent1].[NameID] AS [NameID], [Extent1].[ItemID] AS [ItemID], [Extent1].[ItemValue] AS [ItemValue] FROM [dbo].[DBItemList] AS [Extent1]

四、ObjectQuery LINQ 風格擴充方法 (字串為基礎的查詢建構)

ObjectQuery 提供一組接受 ESQL 字串片段的擴充方法,支援鏈式呼叫:

方法簽名說明範例
WhereWhere(predicate, params ObjectParameter[])篩選條件q.Where("it.ItemValue = 5 AND it.NameID = 'n01'")
OrderByOrderBy(keys, params ObjectParameter[])排序q.OrderBy("it.ItemValue, it.ItemID DESC")
SelectSelect(projection, params ObjectParameter[])投影 (回傳 DbDataRecord)q.Select("it.ItemValue AS a, it.NameID")
SelectValueSelectValue<T>(projection, ...)投影單一值 (回傳 ObjectQuery<T>)q.SelectValue<int>("it.ItemValue + it.AutoId")
TopTop(count, ...)取前 N 筆q.Top("3")
SkipSkip(keys, count, ...)跳過前 N 筆 (需先 OrderBy)q.OrderBy("it.ItemValue").Skip("it.ItemValue", "5")
GroupByGroupBy(keys, projection, ...)分組彙總q.GroupBy("it.ItemID", "it.ItemID, SUM(it.ItemValue) AS ValueSum")
IncludeInclude(path)急載入關聯導航屬性ctx.DBItem.Include("DBItemList")

分頁:Skip + Top 組合


// 跳過前 5 筆,取 3 筆 (第 2 頁,頁面大小 3)
var q = ctx.DBItemList.OrderBy("it.ItemValue").Skip("it.ItemValue", "5").Top("3");
// 產生 T-SQL: SELECT TOP (3) ... FROM (SELECT ..., row_number() OVER (ORDER BY ...) AS rn ... ) WHERE rn > 5

Include 急載入 vs 显式 Load()


// 方式一:Include (單次查詢 JOIN 載入)
var q = ctx.DBItem.Include("DBItemList");
foreach (var item in q)
    foreach (var child in item.DBItemList) Console.WriteLine(child.NameID);

// 方式二:显式 Load (兩次查詢)
var q2 = ctx.DBItem;
foreach (var item in q2)
{
    item.DBItemList.Load(); // 觸發第二次查詢
    foreach (var child in item.DBItemList) Console.WriteLine(child.NameID);
}

Include 急載入示意圖

五、ESQL 基礎語法元素

  • 註解:-- 單行註解
  • 成員存取:. (如 it.ItemValue)
  • 分行/陳述式結束:;

六、運算子完整清單

類別運算子備註
算術+ - * / % - (一元負號)
比較= > >= < <= != <>
IS NULL IS NOT NULL空值判斷
字串比較LIKE NOT LIKE% (多字元) _ (單字元) [] (字元集合) [^] (排除集合)
邏輯AND && OR || NOT !
區間BETWEEN ... AND ... NOT BETWEEN包含邊界
IN {v1,v2,...} NOT IN集合成員資格
EXISTS (subquery) NOT EXISTS子查詢存在性
分頁 (原生)SKIP n LIMIT mESQL 原生分頁語法

七、集合運算 (Set Operations)

運算關鍵字行為範例
聯集UNION / UNION ALLUNION 去重,UNION ALL 保留重複(SELECT ... WHERE id='c' OR id='a') UNION (SELECT ... WHERE id='c' OR id='b')
差集EXCEPT從左集合移除右集合相同項(SELECT ... WHERE id='c' OR id='a') EXCEPT (SELECT ... WHERE id='c' OR id='b')
交集INTERSECT取兩集合共同項(SELECT ... WHERE id='c' OR id='a') INTERSECT (SELECT ... WHERE id='c' OR id='b')
任一元素ANYELEMENT(collection)取集合第一個元素ANYELEMENT(SELECT VALUE it FROM ctx.DBItemList AS it WHERE it.ItemID='a')
重疊檢查OVERLAPS兩集合是否有交集 (回傳 Boolean)(SELECT ... WHERE id='c' OR id='b') OVERLAPS (SELECT ... WHERE id='a' OR id='b')
去重SET(collection)移除集合重複項 (等同 DISTINCT)SET(SELECT VALUE it.ItemID FROM ctx.DBItemList AS it)

集合運算範例輸出

總結

Entity SQL 雖以字串為基礎,但提供了豐富的型別系統、物件導向查詢能力、繼承多型支援,並能無縫對接資料庫原生函數。配合 ObjectQuery 的 LINQ 風格建構方法與 ToTraceString() 除錯,開發者可在動態查詢、複雜報表、大量資料操作等場景中靈活運用,與 LINQ to Entities 互補共存。

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