dynamic在給我們帶來方便的同時,也需注意一些問題,最近在項目中就遇見過一些問題,在此特意進行記錄。
在使用過程報錯:'object' does not contain a definition for 'SortedQty',其中“SortedQty”為dynamic類型對象的一個屬性
1、用EF框架從數據庫內查詢數據,返回一個dynamic類型的數據集。從代碼表達更為直觀,直接上代碼:
1
Task<dynamic> GetSortingProgressBySortedQty()
{
return _repositoryStat.GetAll().Where(p => p.SortedSeconds > 0).OrderByDescending(p => p.Id).Select(p => new 2 { 3 p.SortDate, 4 p.SortLineId, 5 p.SortingLineCode, 6 p.SortState, 7 p.TotalSortQty, 8 p.SortedQty, 9 p.WaveCode, 10 p.SortStartTime, 11 p.SortFinishedTime, 12 p.TotalCompletedOrderQty, 13 p.TotalCompletedRoutes, 14 NormalDownMinutes = p.NormalDowntime ?? 0, 15 FaultDownMinutes = p.FaultDowntime ?? 0, 16 SortedMinutes = (int)((p.SortFinishedTime ?? DateTime.Now) - (p.SortStartTime ?? DateTime.Now)).TotalMinutes, 17 SortingLineName = sortingLineInfo[p.SortLineId.Value] 18 19 });
}
2、調用上述代碼方法返回的dynamic類型數據集
var sortingProgress = await stockOutWaveStatAppService.GetSortingProgressBySortedQty(); int qtyProduct = 0, qtyRoute = 0, qtyCustomer = 0; foreach (var item in sortingProgress ) { qtyProduct += item.SortedQty; qtyRoute += item.TotalCompletedRoutes; qtyCustomer += item.TotalCompletedOrderQty; lstResult.Add(new GetSortProcessInfoRepsoneDto() { SortDate = item.SortDate.ToString("yyyy-MM-dd"), SortlineCode = item.SortingLineCode, SortlineDesc = item.SortingLineName, BeginTime = item.SortStartTime.ToString("yyyy-MM-dd HH:mm:ss"), EndTime = item.SortFinishedTime.ToString("yyyy-MM-dd HH:mm:ss"), QtyProdcutTot = item.SortedQty, QtyRouteTot = item.TotalCompletedRoutes, QtyCustomerTot = item.TotalCompletedOrderQty, QtyProduct = 0, QtyRoute = 0, QtyCustomer = 0, DmTaskNo = item.WaveCode, Efficiency = item.SortQtyEveryHours, Status = item.SortState == 100 ? 2 : item.SortState }); }
在執行這個循環使用對象內的屬性時就會報:'object' does not contain a definition for 'SortedQty'的錯誤。
此問題一直困擾很久,最初以為是屬於的數據類型不匹配造成的,但通過實驗測試並不是該問題。
經過一系列的測試和排查后,后面發現在方法Select(p=>new{ }) 將其更改為 Select(p=>new SortProcessInfoRepsone { }) ,並創建SortProcessInfoRepsone類及其相關的屬性,此問題就解決了。
從報錯的內容上分析,其實就未對對象的屬性進行定義,然后就使進而不正確。
然而我居然通定義實體類並采用Select(p=>new SortProcessInfoRepsone { }) 能解決,但並不想這樣處理,因為調用者和被調用者不在同一個程序集內,兩者其實是通過接口隔離進行調用的,並且被調用者有多地方使用,不能因為這個調用而改變現有,故而最后我采用的方法是在調用方法內通過獲取這個dynamic數據集后將其轉換為Json字符串,再將Json字符串轉成一個定義的類對象,然后再使用即可:
1 public async Task<ActionResult<string>> GetWcsBin() 2 { 3 var sbins = await storageBinAppService.GetAll(new StorageBins.Dto.StorageBinGetAllInput() { MaxResultCount = int.MaxValue }); //獲取dynamic類型數據集 4 GetWcsBinAdapter wcsBinAdapter = new GetWcsBinAdapter(); 5 string result = wcsBinAdapter.TransformDtoToJson(sbins); 6 return new JsonResult(result); 7 } 8 9 public override string TransformDtoToJson<TDto>(TDto dto) 10 { 11 string jsonStr = base.TransformDtoToJson(dto); //轉JSON字符串 12 List<GetSortProcessInfoDto> getSortProcessInfo = this.TransformJsonToDto<List<GetSortProcessInfoDto>>(jsonStr); //再將JSON字符串轉成自定義的類對象 13 List<GetSortProcessInfoRepsoneDto> lstResult = new List<GetSortProcessInfoRepsoneDto>(); 14 int qtyProduct = 0, qtyRoute = 0, qtyCustomer = 0; 15 foreach (var item in getSortProcessInfo) 16 { 17 qtyProduct += item.SortedQty; 18 qtyRoute += item.TotalCompletedRoutes; 19 qtyCustomer += item.TotalCompletedOrderQty; 20 lstResult.Add(new GetSortProcessInfoRepsoneDto() 21 { 22 SortDate = item.SortDate.ToString("yyyy-MM-dd"), 23 SortlineCode = item.SortingLineCode, 24 SortlineDesc = item.SortingLineName, 25 BeginTime = item.SortStartTime.ToString("yyyy-MM-dd HH:mm:ss"), 26 EndTime = item.SortFinishedTime.ToString("yyyy-MM-dd HH:mm:ss"), 27 QtyProdcutTot = item.SortedQty, 28 QtyRouteTot = item.TotalCompletedRoutes, 29 QtyCustomerTot = item.TotalCompletedOrderQty, 30 QtyProduct = 0, 31 QtyRoute = 0, 32 QtyCustomer = 0, 33 DmTaskNo = item.WaveCode, 34 Efficiency = item.SortQtyEveryHours, 35 Status = item.SortState == 100 ? 2 : item.SortState 36 }); 37 } 38 lstResult.ForEach(x => { x.QtyProduct = qtyProduct; x.QtyRoute = qtyRoute; x.QtyCustomer = qtyCustomer; }); 39 return base.TransformDtoToJson(lstResult); 40 }