static async Task AddOrUpdateAsync(BiblioCacheContext context, EntityItem item) { try { // 保存到本地数据库 context.Entities.Add(item); await context.SaveChangesAsync(); } catch (Exception ex) { SqliteException sqlite_exception = ex.InnerException as SqliteException; if (sqlite_exception != null && sqlite_exception.SqliteErrorCode == 19) { // PII 发生重复了 goto UPDATE; } else { throw ex; } } UPDATE: // 更新到本地数据库 context.Entities.Update(item); await context.SaveChangesAsync(); }
public static PatronItem GetPatronItem(string pii) { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } var patron = context.Patrons .Where(o => o.PII == pii) .FirstOrDefault(); return(patron); } }
// result.Value // 0 没有找到记录。没有发生更新 // 1 成功更新 public static async Task <NormalResult> UpdateEntityXmlAsync(string pii, string item_xml, byte[] timestamp) { try { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } // 先尝试从本地实体库中获得原记录 var entity_record = context.Entities.Where(o => o.PII == pii).FirstOrDefault(); if (entity_record == null) { return new NormalResult { Value = 0 } } ; entity_record.Xml = item_xml; entity_record.Timestamp = timestamp; // 保存到本地数据库 context.Entities.Update(entity_record); await context.SaveChangesAsync(); return(new NormalResult { Value = 1 }); } } catch (Exception ex) { WpfClientInfo.WriteErrorLog($"UpdateEntityXmlAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}"); return(new NormalResult { Value = -1, ErrorInfo = $"UpdateEntityXmlAsync() 出现异常: {ex.Message}" }); } }
public static NormalResult DeleteLocalPatronRecord(string strXml) { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } XmlDocument dom = new XmlDocument(); try { dom.LoadXml(strXml); } catch (Exception ex) { return(new NormalResult { Value = -1, ErrorInfo = $"读者记录装载进入 XMLDOM 时出错:{ex.Message}", ErrorCode = "loadXmlError" }); } /* * string pii = DomUtil.GetElementText(dom.DocumentElement, "barcode"); * if (string.IsNullOrEmpty(pii)) * pii = "@refID:" + DomUtil.GetElementText(dom.DocumentElement, "refID"); */ string pii = GetPii(dom); var patron = context.Patrons .Where(o => o.PII == pii) .FirstOrDefault(); if (patron != null) { context.Patrons.Remove(patron); context.SaveChanges(); } return(new NormalResult { Value = 0 }); } }
public static string GetBiblioSummaryFromLocal(string pii) { try { using (BiblioCacheContext context = new BiblioCacheContext()) { var item = context.BiblioSummaries.Where(o => o.PII == pii).FirstOrDefault(); if (item != null && string.IsNullOrEmpty(item.BiblioSummary) == false) { return(item.BiblioSummary); } return(""); } } catch { return(null); } }
// 把读者记录保存(更新)到本地数据库 // result.Value // -1 出错 // 0 没有发生修改 // 1 发生了创建或者修改 public static NormalResult UpdateLocalPatronRecord( GetReaderInfoResult get_result, DateTime lastWriteTime) { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } XmlDocument dom = new XmlDocument(); try { dom.LoadXml(get_result.ReaderXml); } catch (Exception ex) { return(new NormalResult { Value = -1, ErrorInfo = $"读者记录装载进入 XMLDOM 时出错:{ex.Message}", ErrorCode = "loadXmlError" }); } /* * string pii = DomUtil.GetElementText(dom.DocumentElement, "barcode"); * if (string.IsNullOrEmpty(pii)) * pii = "@refID:" + DomUtil.GetElementText(dom.DocumentElement, "refID"); */ string pii = GetPii(dom); var patron = context.Patrons .Where(o => o.PII == pii) .FirstOrDefault(); if (patron != null) { // 如果已经存在的读者记录比打算写入的要新,则放弃写入 if (patron.LastWriteTime > lastWriteTime) { return new NormalResult { Value = 0 } } ; Set(patron, dom); context.Patrons.Update(patron); } else { patron = new PatronItem { PII = pii?.ToUpper(), }; Set(patron, dom); context.Patrons.Add(patron); } context.SaveChanges(); return(new NormalResult { Value = 1 }); } void Set(PatronItem patron, XmlDocument dom) { string cardNumber = DomUtil.GetElementText(dom.DocumentElement, "cardNumber"); cardNumber = cardNumber.ToUpper(); if (string.IsNullOrEmpty(cardNumber) == false) { cardNumber = "," + cardNumber + ","; } if (get_result.RecPath != null) { patron.RecPath = get_result.RecPath; } patron.Bindings = cardNumber; patron.Xml = get_result.ReaderXml; patron.Timestamp = get_result.Timestamp; patron.LastWriteTime = lastWriteTime; } }
// 从本地数据库获取读者记录 // parameters: // buildBorrowInfo 是否根据本地动作信息合成 borrows/borrow 元素 // return.Value: // -1 出错 // 0 读者记录没有找到 // 1 成功 public static GetReaderInfoResult GetReaderInfoFromLocal(string pii, bool buildBorrowInfo) { try { using (BiblioCacheContext context = new BiblioCacheContext()) { if (_cacheDbCreated == false) { context.Database.EnsureCreated(); _cacheDbCreated = true; } pii = pii?.ToUpper(); string query = $",{pii},"; var patrons = context.Patrons .Where(o => o.PII == pii || o.Bindings.Contains(query)) .ToList(); if (patrons.Count == 0) { return new GetReaderInfoResult { Value = 0, ErrorInfo = $"PII 为 '{pii}' 的本地读者记录没有找到" } } ; // 命中读者记录多于一条 if (patrons.Count > 1) { return(new GetReaderInfoResult { Value = -1, ErrorInfo = $"装载本地读者记录失败:'{pii}' 检索命中读者记录 {patrons.Count} 条" }); } var patron = patrons[0]; if (buildBorrowInfo) { // 2020/5/8 // 添加用本地信息模拟出来的 borrows/borrow 元素 XmlDocument patron_dom = new XmlDocument(); patron_dom.LoadXml(patron.Xml); SetBorrowInfo(patron_dom, patron.LastWriteTime); patron.Xml = patron_dom.OuterXml; } return(new GetReaderInfoResult { Value = 1, RecPath = patron.RecPath, ReaderXml = patron.Xml, Timestamp = patron.Timestamp }); } } catch (Exception ex) { return(new GetReaderInfoResult { Value = -1, ErrorInfo = $"装载本地读者记录(PII 为 '{pii}')时出现异常: {ex.Message}" }); } }
// 获得册记录信息和书目摘要信息 // 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() }); } }
// 从本地数据库获得册记录信息和书目摘要信息 // .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() }); } }