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

LINQ to SQL 斷連模式常見異常全解析:原因、重現與解決方案

     編輯:關於.NET

前言:斷連模式 (Disconnected) 的核心挑戰

ASP.NET/Web Service 等無狀態環境中,DataContext 存活週期短,實體物件需序列化傳輸、反序列化後 Attach 回新 Context,此過程極易觸發異常。

異常一:ForeignKeyReferenceAlreadyHasValueException

「物件的目前狀態使該作業無效。」

觸發情境

斷連模式下,實體未正確序列化導致關聯屬性內部狀態不一致。

解決方案

SQLMetal 產生代碼時啟用單向序列化:

sqlmetal /conn:"..." /code:Entities.cs /map:Mapping.map /namespace:DMN /serialization:Unidirectional

Unidirectional 產生 [DataContract]、[DataMember] 屬性,支援 WCF/DataContractSerializer。

異常二:SerializationException - 循環參考

「物件圖包含循環,若停用參考追蹤則無法序列化。」

觸發情境

遞歸儲存時,父物件持有子集合,子物件反向參考父物件,形成雙向循環。

解決方案

  1. 同異常一:啟用 /serialization:Unidirectional (DataContractSerializer 自動處理循環)
  2. 或手動標記 [DataMember(EmitDefaultValue=false)] 忽略反向導航屬性
  3. DTO 模式:傳輸層使用扁平 DTO,避免實體直接序列化

異常三:InvalidOperationException - 缺乏版本/衝突檢查策略

「若實體宣告了版本成員或沒有更新檢查策略,則只能將它附加為沒有原始狀態的已修改實體。」

觸發情境

Attach(entity) 時,實體有主鍵但映射檔無 IsVersion 或 UpdateCheck 設定,LINQ to SQL 無法判斷是否需樂觀鎖。

解決方案

在 .map 檔主鍵欄位加上 IsVersion="true":

<Column Name="ID" Member="ID" Storage="_ID" DbType="Int NOT NULL IDENTITY"
    IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" IsVersion="true" />

或在 DBML 設計工具將主鍵 Auto Generated Value 設為 True。

異常四:NullReferenceException - 導航屬性為 Null

「未將物件參考設定為物件的實例。」

觸發程式碼

var q = from s in students
        select new
        {
            s.Name,
            ClassNO = s.Class.NO // 若學生未分班,s.Class 為 null → 拋出異常
        };

解決方案

// 方案一:三元運算子防禦
ClassNO = s.Class == null ? "" : s.Class.NO

// 方案二:C# 6.0 Null 條件運算子
ClassNO = s.Class?.NO ?? ""

// 方案三:Left Join 寫法 (轉為 SQL 執行)
var q = from s in ctx.Students
        join c in ctx.Classes on s.ClassID equals c.ID into gj
        from c in gj.DefaultIfEmpty()
        select new { s.Name, ClassNO = c.NO ?? "" };

最佳實踐總結表

異常類型核心原因關鍵修正
ForeignKeyReferenceAlreadyHasValueException實體未序列化/反序列化破壞關聯狀態/serialization:Unidirectional
SerializationException (循環)雙向導航屬性形成物件圖循環DataContractSerializer + Unidirectional / DTO
InvalidOperationException (版本)Attach 時缺乏樂觀鎖策略主鍵 IsVersion=true
NullReferenceException查詢投影中直接存取 Null 導航屬性Null 條件運算子 / Left Join
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved