建置完成後,開始建立 Controller,使用 Employees 員工資料表,將所有資料讀取出來:
public IEnumerable<Employees> GetEmployees() { var employees = db.Employees; return employees; }
執行後會發生錯誤:
「不需要資料合約名稱為 'Employees_14BF9F9F0C1DAB0594B23F2EB7695ECA92DD0B880DFF02A4CD9698A2DADBA635:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' 的型別 'System.Data.Entity.DynamicProxies.Employees_14BF9F9F0C1DAB0594B23F2EB7695ECA92DD0B880DFF02A4CD9698A2DADBA635'。請考慮使用 DataContractResolver,或將任何不明的型別新增到已知型別清單 - 例如,可以使用 KnownTypeAttribute 屬性,或將它們新增到會傳送給 DataContractSerializer 的已知型別清單。」
這是由於未禁用 Entity Framework 建立 Proxy 執行個體,所以可以使用以下兩種方法解決:
1.
在 Models 目錄下 Northwind 檔案中的 Northwind.Context.tt 之 Northwind.Context.cs 中,加上 this.Configuration.ProxyCreationEnabled = false;public NORTHWNDEntities() : base("name=NORTHWNDEntities") { this.Configuration.ProxyCreationEnabled = false; }
2.
或者建立一個 BaseApiController 來使所有 Api 都繼承於它,而只要是共用方法、變數、函式都可以寫在裡面:
public class BaseApiController : ApiController { protected NORTHWNDEntities db = new NORTHWNDEntities(); public BaseApiController() { db.Configuration.ProxyCreationEnabled = false; } }
其實兩種方法都可以解決這問題,只是程式碼擺的位置不一樣。
重新執行專案,同一個 Api,執行後會還是會發生錯誤:
「類型 'System.Collections.Generic.HashSet`1[[MVVMwithExtjs.Models.Employees, MVVMwithExtjs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' 的物件圖形包含循環,且如果已停用參照追蹤,便無法被序列化。」
遇到循環參考,其實 KKBruce 在 ASP.NET WEB API - ENTITY FRAMEWORK(EDMX) NAVIGATION PROPERTY引發的JSON物件循環參考錯誤 和保哥 在 ASP.NET Web API 無法輸出 Entity Framework 物件的解法 已經有說明過了,最佳解為「用 Partial Class 與 MetadataType 的方式擴充這些由 Visual Studio 幫我們產生的類別」。
如果隱藏輸出循環參考的資料,將會變成以下格式:
[ { "$id": "1", "Category": { "$id": "2", "Products": [ { "$id": "3", "Category": { "$ref": "2" }, "Id": 2, "Name": "Yogurt" }, { "$ref": "1" } ], "Id": 1, "Name": "Diary" }, "Id": 1, "Name": "Whole Milk" }, { "$ref": "3" } ]物件多了 $id,甚至是整個物件內就只有一個 $ref ,資料變得較難閱讀。
因為使用 WebApi 就必須確認資料的完整性,如果都是在微軟的環境下當然沒有問題,但是資料如果提供給手機程式使用,或者是跨平台的環境中,這種資料格式就不見得在不同的環境中可以閱讀。
我的解法,是將這些循環參考的資料在送出之前,將循環參考的資料設為 null。
public IEnumerableGetEmployees() { var employees = db.Employees; foreach (Employees employee in employees) { employee.Employees1 = null; employee.Employees2 = null; } return employees; }
最後就會得到以下結果:
如果還需要更詳細的資料就另外再寫一個 API 就好了,在一個 API 若是給予太多資訊且又是公開資訊讀取,反而可能會造成 Server 的負擔,最重要的是:「資料的完整性」。
沒有留言 :
張貼留言