// 获得册记录信息和书目摘要信息 // parameters: // style 风格。network 表示只从网络获取册记录;否则优先从本地获取,本地没有再从网络获取册记录。无论如何,书目摘要都是尽量从本地获取 // .Value // 0 没有找到 // 1 找到 public static async Task <GetEntityDataResult> GetEntityDataAsync(string pii, string style) { bool network = StringUtil.IsInList("network", style); try { using (var releaser = await _channelLimit.EnterAsync()) { SipChannel channel = await GetChannelAsync(); try { GetEntityDataResult result = null; List <NormalResult> errors = new List <NormalResult>(); EntityItem entity_record = null; // *** // 第一步:获取册记录 { // 再尝试从 dp2library 服务器获取 // TODO: ItemXml 和 BiblioSummary 可以考虑在本地缓存一段时间 int nRedoCount = 0; REDO_GETITEMINFO: var get_result = await _channel.GetItemInfoAsync("", pii); if (get_result.Value == -1) { errors.Add(new NormalResult { Value = -1, ErrorInfo = get_result.ErrorInfo, ErrorCode = get_result.ErrorCode }); } else if (get_result.Result.CirculationStatus_2 == "01") { errors.Add(new NormalResult { Value = -1, ErrorInfo = get_result.Result.AF_ScreenMessage_o, ErrorCode = get_result.Result.CirculationStatus_2 }); } else if (get_result.Result.CirculationStatus_2 == "13") { errors.Add(new NormalResult { Value = -1, ErrorInfo = get_result.Result.AF_ScreenMessage_o, ErrorCode = "itemNotFound" }); } else { XmlDocument itemdom = new XmlDocument(); itemdom.LoadXml("<root />"); string state = ""; if (get_result.Result.CirculationStatus_2 == "12") { state = "丢失"; } DomUtil.SetElementText(itemdom.DocumentElement, "state", state); DomUtil.SetElementText(itemdom.DocumentElement, "barcode", get_result.Result.AB_ItemIdentifier_r); DomUtil.SetElementText(itemdom.DocumentElement, "location", get_result.Result.AQ_PermanentLocation_o); DomUtil.SetElementText(itemdom.DocumentElement, "currentLocation", get_result.Result.AP_CurrentLocation_o); DomUtil.SetElementText(itemdom.DocumentElement, "accessNo", get_result.Result.CH_ItemProperties_o); // 借书时间 { string borrowDateString = get_result.Result.CM_HoldPickupDate_18; if (string.IsNullOrEmpty(borrowDateString) == false) { if (DateTime.TryParseExact(borrowDateString, "yyyyMMdd HHmmss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime borrowDate)) { DomUtil.SetElementText(itemdom.DocumentElement, "borrowDate", DateTimeUtil.Rfc1123DateTimeStringEx(borrowDate)); DomUtil.SetElementText(itemdom.DocumentElement, "borrower", "***"); } else { // 报错,时间字符串格式错误,无法解析 } } } // 应还书时间 { string returnningDateString = get_result.Result.AH_DueDate_o; if (string.IsNullOrEmpty(returnningDateString) == false) { if (DateTime.TryParseExact(returnningDateString, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime returningDate)) { DomUtil.SetElementText(itemdom.DocumentElement, "returningDate", DateTimeUtil.Rfc1123DateTimeStringEx(returningDate)); } else { // 报错,时间字符串格式错误,无法解析 } } } result = new GetEntityDataResult { Value = 1, ItemXml = itemdom.OuterXml, ItemRecPath = get_result.Result.AB_ItemIdentifier_r, Title = get_result.Result.AJ_TitleIdentifier_r, }; /* * // 保存到本地数据库 * await AddOrUpdateAsync(context, new EntityItem * { * PII = pii, * Xml = item_xml, * RecPath = item_recpath, * Timestamp = timestamp, * }); */ } } // *** /// 第二步:获取书目摘要 // 完全成功 if (result != null && errors.Count == 0) { return(result); } if (result == null) { return new GetEntityDataResult { Value = errors[0].Value, ErrorInfo = errors[0].ErrorInfo, ErrorCode = errors[0].ErrorCode } } ; result.ErrorInfo = errors[0].ErrorInfo; result.ErrorCode = errors[0].ErrorCode; return(result); } finally { ReturnChannel(channel); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"GetEntityDataAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
// 从本地数据库获得册记录信息和书目摘要信息 // .Value // 0 没有找到 // 1 找到一种 // 2 两种都找到了 public static GetEntityDataResult LocalGetEntityData(string pii) { try { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } GetEntityDataResult result = null; // *** // 第一步:获取册记录 // 从本地实体库中获得记录 var entity_record = context.Entities.Where(o => o.PII == pii).FirstOrDefault(); // EntityItem entity_record = null; // testing if (entity_record != null) { result = new GetEntityDataResult { Value = 1, ItemXml = entity_record.Xml, ItemRecPath = entity_record.RecPath, Title = "", } } ; // *** /// 第二步:获取书目摘要 // 从本地书目库中获取书目摘要 var item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault(); if (item != null && string.IsNullOrEmpty(item.BiblioSummary) == false) { if (result == null) { result = new GetEntityDataResult(); } result.Title = item.BiblioSummary; result.Value++; } if (result == null) { return new GetEntityDataResult { Value = 0 } } ; return(result); } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"LocalGetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"LocalGetEntityDataAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
// 获得册记录信息和书目摘要信息 // parameters: // style 风格。network 表示只从网络获取册记录;否则优先从本地获取,本地没有再从网络获取册记录。无论如何,书目摘要都是尽量从本地获取 // .Value // 0 没有找到 // 1 找到 public static async Task <GetEntityDataResult> GetEntityDataAsync(string pii, string style) { bool network = StringUtil.IsInList("network", style); try { using (var releaser = await _channelLimit.EnterAsync()) using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } LibraryChannel channel = App.CurrentApp.GetChannel(); TimeSpan old_timeout = channel.Timeout; channel.Timeout = TimeSpan.FromSeconds(10); try { GetEntityDataResult result = null; List <NormalResult> errors = new List <NormalResult>(); EntityItem entity_record = null; // *** // 第一步:获取册记录 if (network == false) { // 先尝试从本地实体库中获得记录 entity_record = context.Entities.Where(o => o.PII == pii).FirstOrDefault(); // EntityItem entity_record = null; // testing } if (entity_record != null) { result = new GetEntityDataResult { Value = 1, ItemXml = entity_record.Xml, ItemRecPath = entity_record.RecPath, Title = "", } } ; else { // 再尝试从 dp2library 服务器获取 // TODO: ItemXml 和 BiblioSummary 可以考虑在本地缓存一段时间 int nRedoCount = 0; REDO_GETITEMINFO: long lRet = channel.GetItemInfo(null, "item", pii, "", "xml", out string item_xml, out string item_recpath, out byte[] timestamp, "", out _, out _, out string strError); if (lRet == -1) { if ((channel.ErrorCode == ErrorCode.RequestError || channel.ErrorCode == ErrorCode.RequestTimeOut) && nRedoCount < 2) { nRedoCount++; goto REDO_GETITEMINFO; } // TODO: 这里不着急返回,还需要尝试获得书目摘要 errors.Add(new NormalResult { Value = -1, ErrorInfo = strError, ErrorCode = channel.ErrorCode.ToString() }); /* * return new GetEntityDataResult * { * Value = -1, * ErrorInfo = strError, * ErrorCode = channel.ErrorCode.ToString() * }; */ } else { result = new GetEntityDataResult { Value = 1, ItemXml = item_xml, ItemRecPath = item_recpath, Title = "", }; // 保存到本地数据库 await AddOrUpdateAsync(context, new EntityItem { PII = pii, Xml = item_xml, RecPath = item_recpath, Timestamp = timestamp, }); #if NO context.Entities.Add(new EntityItem { PII = pii, Xml = item_xml, RecPath = item_recpath, Timestamp = timestamp, }); try { await context.SaveChangesAsync(); } catch (Exception ex) { SqliteException sqlite_exception = ex.InnerException as SqliteException; if (sqlite_exception != null && sqlite_exception.SqliteErrorCode == 19) { // PII 发生重复了 } else { throw ex; } } #endif } } // *** /// 第二步:获取书目摘要 // 先尝试从本地书目库中获取书目摘要 var item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault(); if (item != null && string.IsNullOrEmpty(item.BiblioSummary) == false) { if (result == null) { result = new GetEntityDataResult(); } result.Title = item.BiblioSummary; } else { // 从 dp2library 服务器获取书目摘要 int nRedoCount = 0; REDO_GETBIBLIOSUMMARY: long lRet = channel.GetBiblioSummary( null, pii, "", // strConfirmItemRecPath, null, out _, out string strSummary, out string strError); if (lRet == -1) { if ((channel.ErrorCode == ErrorCode.RequestError || channel.ErrorCode == ErrorCode.RequestTimeOut) && nRedoCount < 2) { nRedoCount++; goto REDO_GETBIBLIOSUMMARY; } errors.Add(new NormalResult { Value = -1, ErrorInfo = strError, ErrorCode = channel.ErrorCode.ToString() }); /* * return new GetEntityDataResult * { * Value = -1, * ErrorInfo = strError, * ErrorCode = channel.ErrorCode.ToString(), * }; */ } else { strSummary = strSummary?.Replace(". -- ", "\r\n"); // .Replace("/", "\r\n"); if (result == null) { result = new GetEntityDataResult(); } result.Title = strSummary; // 存入数据库备用 if (lRet == 1 && string.IsNullOrEmpty(strSummary) == false) { try { var exist_item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault(); if (exist_item != null) { if (exist_item.BiblioSummary != strSummary) { exist_item.BiblioSummary = strSummary; context.BiblioSummaries.Update(exist_item); } } else { context.BiblioSummaries.Add(new BiblioSummaryItem { PII = pii, BiblioSummary = strSummary }); } await context.SaveChangesAsync(); } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 中保存 summary 时(PII 为 '{pii}')出现异常:{ExceptionUtil.GetDebugText(ex)}"); } } } /* * return new GetEntityDataResult * { * Value = (int)lRet, * ItemXml = item_xml, * ItemRecPath = item_recpath, * Title = strSummary, * ErrorInfo = strError, * ErrorCode = channel.ErrorCode.ToString() * }; */ } // 完全成功 if (result != null && errors.Count == 0) { return(result); } if (result == null) { return new GetEntityDataResult { Value = errors[0].Value, ErrorInfo = errors[0].ErrorInfo, ErrorCode = errors[0].ErrorCode } } ; result.ErrorInfo = errors[0].ErrorInfo; result.ErrorCode = errors[0].ErrorCode; return(result); } finally { channel.Timeout = old_timeout; App.CurrentApp.ReturnChannel(channel); } } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"GetEntityDataAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new GetEntityDataResult { Value = -1, ErrorInfo = $"GetEntityDataAsync() 出现异常: {ex.Message}", ErrorCode = ex.GetType().ToString() }); } }
// 第二阶段:填充图书信息的 PII 和 Title 字段 async Task FillBookFields(BaseChannel <IRfid> channel, List <Entity> entities, CancellationToken token) { try { foreach (Entity entity in entities) { if (token.IsCancellationRequested) { return; } if (entity.FillFinished == true) { continue; } // 获得 PII // 注:如果 PII 为空,文字中要填入 "(空)" if (string.IsNullOrEmpty(entity.PII)) { if (entity.TagInfo == null) { continue; } Debug.Assert(entity.TagInfo != null); LogicChip chip = LogicChip.From(entity.TagInfo.Bytes, (int)entity.TagInfo.BlockSize, "" // tag.TagInfo.LockStatus ); string pii = chip.FindElement(ElementOID.PII)?.Text; entity.PII = PageBorrow.GetCaption(pii); } // 获得 Title // 注:如果 Title 为空,文字中要填入 "(空)" if (string.IsNullOrEmpty(entity.Title) && string.IsNullOrEmpty(entity.PII) == false && entity.PII != "(空)") { GetEntityDataResult result = await Task <GetEntityDataResult> .Run(() => { return(GetEntityData(entity.PII)); }); if (result.Value == -1) { entity.SetError(result.ErrorInfo); continue; } entity.Title = PageBorrow.GetCaption(result.Title); entity.SetData(result.ItemRecPath, result.ItemXml); } entity.SetError(null); entity.FillFinished = true; } booksControl.SetBorrowable(); } catch (Exception ex) { SetGlobalError("current", ex.Message); } }