/// <summary> /// 填充对于指定功能模块数据的同步到其他站点的历史记录 /// </summary> /// <param name="userHandle"></param> /// <param name="dt"></param> /// <param name="progId"></param> /// <param name="internalId">内码</param> public static void FillSyncDataHistory(LibHandle userHandle, DataTable dt, string progId, string internalId) { if (userHandle == null || dt == null || string.IsNullOrEmpty(progId) || ExistAxpSyncDataInfo == false || ExistLinkSiteTable == false) { return; } try { if (string.IsNullOrEmpty(internalId) == false) { string sql = string.Format("select A.*,C.PERSONNAME,D.SHORTNAME from AXPSYNCDATAHISTORY A " + " left join AXPUSER B on A.USERID = B.USERID " + " left join COMPERSON C on B.PERSONID = C.PERSONID " + " left join AXPLINKSITE D on A.SITEID = D.SITEID " + " where A.PROGID = {0} and A.INTERNALID = {1} " + " order by A.SYNCTIME desc",// 时间降序 LibStringBuilder.GetQuotString(progId), LibStringBuilder.GetQuotString(internalId)); LibDataAccess dataAccess = new LibDataAccess(); dataAccess.ExecuteDataTable(sql, dt, true, 200);//取前200条 } dt.AcceptChanges(); } catch (Exception exp) { LibCommUtils.AddOutput(@"Error\CrossSiteCall", string.Format("error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); } }
/// <summary> /// 添加同步信息到同步信息记录表中 /// </summary> /// <param name="syncInfo"></param> /// <returns></returns> public static bool AddSyncDataRecord(SyncDataInfo syncInfo) { try { if (syncInfo == null || string.IsNullOrEmpty(syncInfo.ProgId) || string.IsNullOrEmpty(syncInfo.InternalId) || string.IsNullOrEmpty(syncInfo.UserId)) { return(false); } string sql = string.Format("insert into AXPSYNCDATAHISTORY(INFOID,PROGID,INTERNALID,BILLNO,USERID,SITEID,SYNCTIME,SYNCOP,SYNCSTATE,SYNCINFO) " + "values({0},{1},{2},{3},{4},{5},{6},{7},{8},{9})", LibStringBuilder.GetQuotString(Guid.NewGuid().ToString()), LibStringBuilder.GetQuotString(syncInfo.ProgId), LibStringBuilder.GetQuotString(syncInfo.InternalId), LibStringBuilder.GetQuotString(syncInfo.BillNo), LibStringBuilder.GetQuotString(syncInfo.UserId), LibStringBuilder.GetQuotString(syncInfo.SiteId), LibDateUtils.DateTimeToLibDateTime(syncInfo.SyncTime), (int)syncInfo.SyncOp, (int)syncInfo.SyncState, LibStringBuilder.GetQuotString(syncInfo.SyncInfo) ); LibDataAccess dataAccess = new LibDataAccess(); int count = dataAccess.ExecuteNonQuery(sql); return(count > 0); } catch (Exception exp) { LibCommUtils.AddOutput("CrossSiteCall", string.Format("error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); return(false); } }
public string Register(RegisterInfo info) { string error = string.Empty; LibDataAccess dataAccess = new LibDataAccess(); string userId = LibSysUtils.ToString(dataAccess.ExecuteScalar(string.Format("select USERID from AXPUSER where USERID={0}", LibStringBuilder.GetQuotString(info.inputId)))); if (string.IsNullOrEmpty(userId)) { string personId = LibSysUtils.ToString(dataAccess.ExecuteScalar(string.Format("select PERSONID from COMPERSON where PERSONNAME={0} and DEPTID={1}", LibStringBuilder.GetQuotString(info.inputName), LibStringBuilder.GetQuotString(info.inputDept)))); //如果遇到同部门同名的情况。建议客户手动创建人员主数据。 if (string.IsNullOrEmpty(personId)) { LibBcfData bcfData = (LibBcfData)LibBcfSystem.Default.GetBcfInstance("com.Person"); DataSet dataSet = bcfData.AddNew(null); DataRow masterRow = dataSet.Tables[0].Rows[0]; masterRow.BeginEdit(); try { if (string.IsNullOrEmpty(LibSysUtils.ToString(masterRow["PERSONID"]))) { masterRow["PERSONID"] = personId = LibCommUtils.GetInternalId().ToString(); } masterRow["PERSONNAME"] = info.inputName; masterRow["GENDER"] = info.gender; masterRow["DEPTID"] = info.inputDept; masterRow["MAIL"] = info.inputEmail; masterRow["PHONENO"] = info.inputPhone; } finally { masterRow.EndEdit(); } dataSet = bcfData.InnerSave(BillAction.AddNew, new object[] { personId }, dataSet); personId = LibSysUtils.ToString(dataSet.Tables[0].Rows[0]["PERSONID"]); } if (!string.IsNullOrEmpty(personId)) { string sql = string.Format("insert into AXPUSER(USERID,USERPASSWORD,PERSONID,ISUSE) values({0},{1},{2},0)", LibStringBuilder.GetQuotString(info.inputId), LibStringBuilder.GetQuotString(info.inputPassword1), LibStringBuilder.GetQuotString(personId)); dataAccess.ExecuteNonQuery(sql); } } else { error = "账号已注册"; } return(error); }
/// <summary> /// 获取指定用户的SSO令牌信息。如果本站点不是SSO管理站点,则从管理站点获取 /// </summary> /// <param name="userHandle"></param> /// <param name="timeOutMs"></param> /// <param name="dataAccess">可选参数:数据库访问器。如果调用时使用了数据库事务,需要将开启了事务的数据库访问器传递进来,避免在本方法中查询数据库时因事务锁表而死锁。</param> /// <returns></returns> public static string GetToken(LibHandle userHandle, int timeOutMs = 30 * 1000, LibDataAccess dataAccess = null) { if (userHandle == null || string.IsNullOrEmpty(userHandle.UserId)) { return(string.Empty); } if (EnvProvider.Default.IsSSOManageSite) { return(userHandle.GetToCheckToken()); } if (string.IsNullOrEmpty(EnvProvider.Default.SSOManageSiteUrl)) { return(string.Empty); } try { string url = string.Format("{0}/sysSvc/getTokenByUserId", EnvProvider.Default.SSOManageSiteUrl); string password = string.Empty; string sql = string.Format("select USERPASSWORD from AXPUSER where USERID={0} And ISUSE=1", LibStringBuilder.GetQuotString(userHandle.UserId)); if (dataAccess == null) { password = LibSysUtils.ToString((new LibDataAccess()).ExecuteScalar(sql)); } else { password = LibSysUtils.ToString(dataAccess.ExecuteScalar(sql)); } var postP = new { userId = userHandle.UserId, pwd = password }; string errorInfo = string.Empty; dynamic result = LibNetUtils.HttpPostCall <dynamic>(url, postP, out errorInfo, timeOutMs); if (string.IsNullOrEmpty(errorInfo) == false || result == null) { return(string.Empty); } else { return((string)result.GetTokenByUserIdResult); } } catch (Exception exp) { LibCommUtils.AddOutput("CrossSiteCall", string.Format("error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); return(string.Empty); } }
/// <summary> /// 向SSOManage站点发起校验令牌信息的请求 /// </summary> /// <param name="ssoInfo">包含令牌信息的参数</param> /// <param name="timeOutMs">超时时间,单位为毫秒,默认为5000毫秒</param> /// <returns>如果验证成功返回true,否则返回false</returns> public static bool CheckSSOLoginState(SSOInfo ssoInfo, int timeOutMs = 5000) { if (ssoInfo == null || string.IsNullOrEmpty(ssoInfo.UserId) || string.IsNullOrEmpty(ssoInfo.Token)) { return(false); } if (EnvProvider.Default.IsSSOManageSite) { LibHandle handle = LibHandleCache.Default.IsExistsHandle(LibHandeleType.PC, ssoInfo.UserId); if (handle != null) { return(handle.Token == ssoInfo.Token); } return(false); } if (string.IsNullOrEmpty(EnvProvider.Default.SSOManageSiteUrl)) { return(false); } try { string url = string.Format("{0}/sysSvc/CheckSSOLoginState", EnvProvider.Default.SSOManageSiteUrl); var postP = new { ssoInfo = ssoInfo }; string errorInfo = string.Empty; dynamic result = LibNetUtils.HttpPostCall <dynamic>(url, postP, out errorInfo, timeOutMs); if (string.IsNullOrEmpty(errorInfo) == false || result == null) { return(false); } else { // 私钥解密 string ret = LibRSAHelper.Decrypt((string)result.CheckSSOLoginStateResult);//对于直接返回基本类型的接口调用,结果会包装成方法名+Result return(ret == "0"); } } catch (Exception exp) { LibCommUtils.AddOutput("CrossSiteCall", string.Format("CheckSSOLoginState error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); return(false); } }
public void UpdateAttachStruct(LibAttachData attachData, List <string> listSql) { if (string.IsNullOrEmpty(attachData.AttachSrc)) { attachData.AttachSrc = LibCommUtils.GetInternalId().ToString(); StringBuilder builder = new StringBuilder(); foreach (var item in attachData.PkList) { if (item.Value.GetType() == typeof(string)) { builder.AppendFormat("{0} = {1} and ", item.Key, LibStringBuilder.GetQuotObject(item.Value)); } else { builder.AppendFormat("{0} = {1} and ", item.Key, item.Value); } } if (builder.Length > 0) { builder.Remove(builder.Length - 4, 4); } //更新单据附件关联字段 listSql.Add(string.Format("update {0} set ATTACHMENTSRC='{1}' where {2}", attachData.TableName, attachData.AttachSrc, builder.ToString())); } foreach (var item in attachData.AttachList) { switch (item.Status) { case LibAttachStatus.Add: listSql.Add(string.Format("insert into AXPATTACHMENTRECORD(BELONGTOID,ORDERID,ORDERNUM,ATTACHMENTNAME,CANUSE) values('{0}',{1},{2},'{3}',1)", attachData.AttachSrc, item.OrderId, item.OrderNum, item.AttachmentName)); break; case LibAttachStatus.Modif: listSql.Add(string.Format("update AXPATTACHMENTRECORD set ORDERNUM={2},ATTACHMENTNAME='{3}' where BELONGTOID='{0}' and ORDERID={1}", attachData.AttachSrc, item.OrderId, item.OrderNum, item.AttachmentName)); break; case LibAttachStatus.Delete: listSql.Add(string.Format("update AXPATTACHMENTRECORD set CANUSE=0 where BELONGTOID='{0}' and ORDERID={1}", attachData.AttachSrc, item.OrderId)); break; } } }
/// <summary> /// 检查用户账户是否存在 /// </summary> /// <param name="userId"></param> /// <returns></returns> public static bool CheckUserExist(string userId) { if (string.IsNullOrEmpty(userId)) { return(false); } try { LibDataAccess dataAccess = new LibDataAccess(); int count = LibSysUtils.ToInt32(dataAccess.ExecuteScalar(string.Format("select count(*) from AXPUSER where USERID={0} AND ISUSE=1", LibStringBuilder.GetQuotString(userId)))); return(count > 0); } catch (Exception exp) { LibCommUtils.AddOutput("CrossSiteCall", string.Format("error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); return(false); } }
/// <summary> /// 根据信息唯一标识InfoId更新数据同步的历史结果 /// </summary> /// <param name="syncInfo"></param> /// <returns></returns> public static bool UpdateSyncDataRecord(SyncDataInfo syncInfo) { try { if (syncInfo == null || string.IsNullOrEmpty(syncInfo.InfoId)) { return(false); } string sql = string.Format("update AXPSYNCDATAHISTORY set SYNCSTATE={0},SYNCINFO={1} where INFOID={2}", (int)syncInfo.SyncState, LibStringBuilder.GetQuotString(syncInfo.SyncInfo), LibStringBuilder.GetQuotString(syncInfo.InfoId) ); LibDataAccess dataAccess = new LibDataAccess(); int count = dataAccess.ExecuteNonQuery(sql); return(count > 0); } catch (Exception exp) { LibCommUtils.AddOutput("CrossSiteCall", string.Format("error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); return(false); } }
public UpLoadFileResult UpLoadUserPicture(Stream stream) { string dirPath = Path.Combine(EnvProvider.Default.RuningPath, "UserPicture"); return(UpLoadPicture(stream, dirPath, LibCommUtils.GetInternalId().ToString())); }
public override string GetMailBody(LibMailParam param, Dictionary <string, string[]> addressDic) { string html = string.Empty; string path = Path.Combine(EnvProvider.Default.MainPath, "Resource", "MailTpl", "ApproveMailTpl.html"); using (FileStream fs = new FileStream(path, FileMode.Open)) { using (StreamReader reader = new StreamReader(fs, Encoding.Default)) { html = reader.ReadToEnd(); } } html.Replace("@BILL", param.ProgName); html.Replace("@USER", addressDic[param.UserId][0]); html.Replace("@DATE", DateTime.Now.ToShortDateString()); html.Replace("@TEXT", param.Content); if (param.ExpandData.ContainsKey("@IMG")) { string base64 = param.ExpandData["@IMG"]; string imageName = string.Format("{0}-{1}.png", LibDateUtils.GetCurrentDateTime(), LibCommUtils.GetInternalId()); string imgUrl = Path.Combine(".", "PublicData", "Mail", "Image", imageName); using (FileStream fs = new FileStream(imgUrl, FileMode.Create)) { byte[] imageBytes = Convert.FromBase64String(base64); fs.Write(imageBytes, 0, imageBytes.Length); } html.Replace("@IMG", imgUrl); } html.Replace("@LINK", ""); return(html); }
public void UpdateTable(TableSchema schema, bool isDelete) { DataTable table = null; LibDataAccess dataAccess = new LibDataAccess(); int count = (int)dataAccess.ExecuteScalar(string.Format("select count(*) from sysobjects where id = object_id({0})", LibStringBuilder.GetQuotString(schema.Name))); if (count == 0) { CreateTable(schema); } else { using (DbConnection conn = dataAccess.CreateConnection()) { conn.Open(); table = conn.GetSchema("Columns", new string[] { null, null, schema.Name, null }); } if (table != null) { List <string> sql = new List <string>(); List <string> sqlSecond = new List <string>();//第二批执行的sql语句,一般在数据列加完以后执行唯一约束、主键等设置 //如果主键异动,先删除聚集索引 bool isPkChange = IsPkChange(schema.Name, schema.PRIMARY_KEY); if (isPkChange) { sql.Add(GetDropPkConstraintSql(schema.Name)); } //对删除的非聚集索引进行处理 List <string> deleteIndexList = new List <string>(); List <string> addIndexList = new List <string>(); CompareDBIndex(schema.Name, schema.DBIndexs, addIndexList, deleteIndexList); foreach (var item in deleteIndexList) { sql.Add(item); } //再对列进行处理 Dictionary <string, bool> dic = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase); foreach (ColumnSchema col in schema.ColumnSchemaList) { dic.Add(col.Name, false); } foreach (DataRow row in table.Rows) { string columnName = row["COLUMN_NAME"].ToString(); string dataType = row["DATA_TYPE"].ToString(); int size = LibSysUtils.ToInt32(row["CHARACTER_MAXIMUM_LENGTH"]); int digit = LibSysUtils.ToInt32(row["NUMERIC_SCALE"]); string defualtValue = LibSysUtils.ToString(row["COLUMN_DEFAULT"]); bool isFind = false; foreach (ColumnSchema col in schema.ColumnSchemaList) { if (string.Compare(col.Name, columnName, true) == 0) { StringBuilder strBuilder = new StringBuilder(); if (string.Compare(col.ColumnType, dataType, true) != 0 || (col.Size > 0 && col.Size != size) || col.Digit != digit) { foreach (var item in schema.PRIMARY_KEY) { if (string.Compare(col.Name, item, true) == 0) { if (!isPkChange) { isPkChange = true; sql.Add(GetDropPkConstraintSql(schema.Name)); } break; } } //删除默认值约束 strBuilder.Append(GetDropDefaultValueCheckSql(schema.Name, columnName)); //修改字段 strBuilder.AppendLine("ALTER TABLE [dbo].[{0}] ALTER column {1} "); //新建默认值约束 strBuilder.AppendFormat("ALTER TABLE [dbo].[{0}] ADD {1} FOR [{2}]", schema.Name, col.DefaultValueStr, columnName); sql.Add(string.Format(strBuilder.ToString(), schema.Name, col.ColumnTypeStr)); } else if (string.Compare(string.Format(col.DefaultValue), defualtValue) != 0) { foreach (var item in schema.PRIMARY_KEY) { if (string.Compare(col.Name, item, true) == 0) { if (!isPkChange) { isPkChange = true; sql.Add(GetDropPkConstraintSql(schema.Name)); } break; } } //删除默认值约束 strBuilder.Append(GetDropDefaultValueCheckSql(schema.Name, columnName)); //新建默认值约束 strBuilder.AppendFormat("ALTER TABLE [dbo].[{0}] ADD {1} FOR [{2}]", schema.Name, col.DefaultValueStr, columnName); sql.Add(string.Format(strBuilder.ToString(), schema.Name, columnName)); } isFind = true; dic[columnName] = true; break; } } if (isDelete && !isFind) { //原先存在。现在不存在,则考虑删除 //有默认约束依赖该字段,先删除默认约束,再删除字段 //删除默认值约束 StringBuilder strBuilder = new StringBuilder(); strBuilder.Append(GetDropDefaultValueCheckSql(schema.Name, columnName)); //删除字段 strBuilder.AppendLine(string.Format("ALTER TABLE [dbo].[{0}] DROP [{1}] {2}", schema.Name, columnName)); sql.Add(strBuilder.ToString()); } } foreach (var item in dic) { if (!item.Value) { StringBuilder strBuilder = new StringBuilder(); ColumnSchema col = schema.ColumnSchemaList.Find(c => c.Name == item.Key); //新增列 strBuilder.AppendLine(string.Format("ALTER TABLE [dbo].[{0}] ADD {1}", schema.Name, col.ColumnTypeStr)); //新增列默认值约束 strBuilder.Append(col.DefaultValueStr); sql.Add(strBuilder.ToString()); } } //第二批执行的是索引、主键、唯一约束等 //先添加对于具有唯一性约束的字段的数据更新处理Sql,以便其先执行 if (string.IsNullOrEmpty(this.UniqueDataSql) == false && (isPkChange || addIndexList.Count > 0)) { sqlSecond.Add(this.UniqueDataSql); } //对主键的进行标识 if (isPkChange) { sqlSecond.Add(GetAddPkConstraintSql(schema.Name, schema.PRIMARY_KEY)); } //对表的新增非聚集索引进行处理 foreach (var item in addIndexList) { sqlSecond.Add(item); } if (sql.Count > 0 || sqlSecond.Count > 0) { StringBuilder sqlBuilder = new StringBuilder(); foreach (var item in sql) { sqlBuilder.Append(item); } StringBuilder sqlBuilderSecond = new StringBuilder(); foreach (var item in sqlSecond) { sqlBuilderSecond.Append(item); } //提交更新 LibDBTransaction tran = dataAccess.BeginTransaction(); try { if (sqlBuilder.Length > 0) { dataAccess.ExecuteNonQuery(sqlBuilder.ToString()); } //第二批执行的是索引、主键、唯一约束等 if (sqlBuilderSecond.Length > 0) { dataAccess.ExecuteNonQuery(sqlBuilderSecond.ToString()); } tran.Commit(); } catch (Exception exp) { LibCommUtils.AddOutput(@"Update", string.Format("升级数据表异常。\r\nsql:{0}\r\n异常:{1}\r\nStackTrace:{2}", sqlBuilder.ToString(), exp.Message, exp.StackTrace)); tran.Rollback(); } } } } }
/// <summary> /// 同步数据到子站点 /// </summary> protected virtual void CallSynchroData() { if (this.DataSet.Tables.Contains(LibFuncPermission.SynchroDataSettingTableName) == false || CrossSiteHelper.ExistAxpSyncDataInfo == false || CrossSiteHelper.ExistLinkSiteTable == false) { return; } if (this.IsCrossSiteCall) { return; //本身已经是跨站点调用的不通过业务的数据变更触发数据同步,而是由跨站调用集中处理 } BcfSyncConfig syncConfig = this.Template.FuncPermission.SyncConfig; //同步配置 DataTable syncDt = this.DataSet.Tables[LibFuncPermission.SynchroDataSettingTableName]; syncDt.AcceptChanges(); CrossSiteHelper.UpdateSyncDataSetting(syncDt); List <string> siteIdList = new List <string>(); DataRow[] syncRows = syncDt.Select(string.Format("ISSYNCTO = 1")); if (syncRows != null && syncRows.Length > 0) { foreach (DataRow row in syncRows) { siteIdList.Add(LibSysUtils.ToString(row["SITEID"])); } } else { return;//因为同步配置会在获取到Dataset时就填充好(上一层用户配置或者默认的可向其同步的子站点), 如果从DataSet的同步信息从表配置中未筛选到同步信息行,则说明不需要同步了。 } LibSyncDataOpType opType = LibSyncDataOpType.Modify; //同步数据到站点 Dictionary <string, LinkSiteInfo> linkSites = CrossSiteHelper.GetLinkSites(siteIdList.ToArray(), true); if (linkSites != null && linkSites.Count > 0) { DataRow masterRow = this.DataSet.Tables[0].Rows[0]; Dictionary <string, object> mainRowPks = new Dictionary <string, object>(); string internalId = LibSysUtils.ToString(masterRow["INTERNALID"]); if (masterRow.RowState == DataRowState.Added || this.BillAction == BillAction.Delete) { foreach (DataColumn column in this.DataSet.Tables[0].PrimaryKey) { mainRowPks[column.ColumnName] = masterRow[column.ColumnName]; } if (this.BillAction == BillAction.Delete) { opType = LibSyncDataOpType.Delete; } else { opType = LibSyncDataOpType.AddNew; } } else { foreach (DataColumn column in this.DataSet.Tables[0].PrimaryKey) { mainRowPks[column.ColumnName] = masterRow[column.ColumnName, DataRowVersion.Original]; } opType = LibSyncDataOpType.Modify; } //移除虚表 List <string> toRemoveTable = new List <string>(); //子表或子子表中删除行的信息 Dictionary <string, LibChangeRecord> subDeleteChanges = DataSetManager.GetChangeRecord(this.DataSet); if (subDeleteChanges != null && subDeleteChanges.Count > 0) { //只保留子表的删除行信息 foreach (string tableName in subDeleteChanges.Keys) { if (tableName == this.DataSet.Tables[0].TableName) { subDeleteChanges[tableName].Remove.Clear(); } subDeleteChanges[tableName].Add.Clear(); subDeleteChanges[tableName].Modif.Clear(); } } DataSet toSendDataset = this.DataSet.Copy(); foreach (DataTable dt in toSendDataset.Tables) { if (dt.ExtendedProperties.ContainsKey(TableProperty.IsVirtual) && (bool)dt.ExtendedProperties[TableProperty.IsVirtual]) { toRemoveTable.Add(dt.TableName); } if (dt.TableName.Equals(this.DataSet.Tables[0].TableName) == false && syncConfig != null && syncConfig.NonSyncSubTables.Contains(dt.TableName)) { //非主表且是不需要同步的子表,则清空其中的数据 dt.Clear(); if (subDeleteChanges.Keys.Contains(dt.TableName)) { subDeleteChanges.Remove(dt.TableName); } } } toRemoveTable.ForEach(tableName => { toSendDataset.Tables.Remove(tableName); }); toSendDataset.AcceptChanges(); //存在可访问的从站,则合并获取从站的系统消息数据 ExecuteBcfMethodParam callParams = new ExecuteBcfMethodParam() { ProgId = this.ProgId, MethodName = "SynchroData", MethodParam = ExecuteBcfMethodParam.ConvertMethodParams(new object[] { this.BillAction, mainRowPks, subDeleteChanges, this.ExtendBcfParam, toSendDataset }), TimeoutMillSecs = 30000, //设置超时时间,单位毫秒 IsSynchroDataCall = true }; try { //阻塞模式调用远程方法 Dictionary <string, ExecuteBcfMethodResult> dicRets = CrossSiteHelper.CrossSiteBcfCall(this.Handle.Handle, linkSites.Keys.ToList(), callParams, this.DataAccess); if (dicRets == null || dicRets.Keys.Count == 0) { return; } string retStr = string.Empty; string syncInfo = string.Empty; foreach (string key in dicRets.Keys) { syncInfo = string.Empty; if (dicRets[key] != null && dicRets[key].Messages != null && dicRets[key].Messages.Count > 0) { dicRets[key].Messages.ForEach(msg => { syncInfo += msg.Message + "\r\n"; msg.Message = string.Format("同步到站点:{0},消息:{1}", linkSites[key].ShortName, msg.Message); this.ManagerMessage.AddMessage(msg); }); } CrossSiteHelper.AddSyncDataRecord(new SyncDataInfo() { ProgId = this.ProgId, InternalId = internalId, BillNo = (mainRowPks.Count > 0) ? Convert.ToString(mainRowPks.Values.First()) : "", UserId = this.Handle.UserId, SiteId = key, SyncTime = DateTime.Now, SyncOp = opType, SyncState = dicRets[key].Messages.HasError() ? LibSyncDataState.SyncError : LibSyncDataState.Synced, SyncInfo = syncInfo }); } } catch (Exception exp) { LibCommUtils.AddOutput(@"Error\CrossSiteCall", string.Format("CallSynchroData error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); this.ManagerMessage.AddMessage(LibMessageKind.SysException, string.Format("同步数据到站点异常:{0}", exp.Message)); } } }
/// <summary> /// 填充指定用户对于指定功能模块数据的同步到其他站点的配置,如果没有则构造配置 /// </summary> /// <param name="userHandle"></param> /// <param name="dt"></param> /// <param name="progId"></param> public static void FillSyncDataSetting(LibHandle userHandle, DataTable dt, string progId) { if (userHandle == null || dt == null || string.IsNullOrEmpty(progId) || ExistAxpSyncDataInfo == false || ExistLinkSiteTable == false) { return; } //构建当前用户对所有站点的同步选项 Dictionary <string, LinkSiteInfo> linkSites = GetLinkSites(null, true); if (linkSites == null || linkSites.Count == 0) { return; } string siteIdStrs = string.Empty; foreach (string key in linkSites.Keys) { siteIdStrs += LibStringBuilder.GetQuotString(key) + ","; } siteIdStrs = siteIdStrs.Substring(0, siteIdStrs.Length - 1); try { string sql = string.Format("select A.*,C.PERSONNAME,D.SHORTNAME from AXPSYNCDATASETTING A " + " left join AXPUSER B on A.USERID = B.USERID " + " left join COMPERSON C on B.PERSONID = C.PERSONID " + " left join AXPLINKSITE D on A.SITEID = D.SITEID " + " where A.PROGID = {0} and A.USERID = {1} and A.SITEID in ({2})" + " order by A.SITEID asc",// 站点代码升序 LibStringBuilder.GetQuotString(progId), LibStringBuilder.GetQuotString(userHandle.UserId), siteIdStrs); LibDataAccess dataAccess = new LibDataAccess(); dataAccess.ExecuteDataTable(sql, dt); DataRow[] rows = null; if (dt.Rows.Count < linkSites.Count) { if (linkSites != null && linkSites.Count > 0) { dt.BeginLoadData(); try { DataRow newRow = null; foreach (string key in linkSites.Keys) { rows = dt.Select(string.Format("SITEID = {0}", LibStringBuilder.GetQuotString(key))); if (rows == null || rows.Length == 0) { //对于没有配置的站点,增加默认配置 并保存到数据库 newRow = dt.NewRow(); newRow.BeginEdit(); Guid guid = Guid.NewGuid(); newRow["SETTINGID"] = guid.ToString(); newRow["PROGID"] = progId; newRow["USERID"] = userHandle.UserId; newRow["ISSYNCTO"] = linkSites[key].IsSlave ? 1 : 0;//默认仅向子站点同步 newRow["SITEID"] = key; newRow["SHORTNAME"] = linkSites[key].ShortName; newRow.EndEdit(); dt.Rows.Add(newRow); string insertSql = string.Format("insert into AXPSYNCDATASETTING(SETTINGID,PROGID,USERID,ISSYNCTO,SITEID) " + "values({0},{1},{2},{3},{4})", LibStringBuilder.GetQuotString(guid.ToString()), LibStringBuilder.GetQuotString(progId), LibStringBuilder.GetQuotString(userHandle.UserId), linkSites[key].IsSlave ? 1 : 0,//默认仅向子站点同步 LibStringBuilder.GetQuotString(key) ); dataAccess.ExecuteNonQuery(insertSql); } } } finally { dt.EndLoadData(); } } } dt.AcceptChanges(); } catch (Exception exp) { LibCommUtils.AddOutput(@"Error\CrossSiteCall", string.Format("error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); } }
/// <summary> /// 向多个目标站点发起跨站Bcf方法调用请求。 /// 此方法执行时会阻塞 /// 如果有向多个站点请求执行,会同时(并发线程)向多个站点发起请求,请求完毕后再汇总执行结果返回 /// 如果参数有误会抛出异常 /// </summary> /// <param name="handle">当前用户的标识Handle</param> /// <param name="linkSiteIds">目标站点代码列表</param> /// <param name="callParams">包含SSO令牌信息、请求方法、请求参数等callParams</param> /// <param name="dataAccess">可选参数:数据库访问器。如果调用时使用了数据库事务,需要将开启了事务的数据库访问器传递进来,避免在本方法中查询数据库时因事务锁表而死锁。</param> /// <returns>返回执行结果字典,键值为目标站点Id,值为执行结果</returns> public static Dictionary <string, ExecuteBcfMethodResult> CrossSiteBcfCall(string handle, List <string> linkSiteIds, ExecuteBcfMethodParam callParams, LibDataAccess dataAccess = null) { if (string.IsNullOrEmpty(handle) || linkSiteIds == null || linkSiteIds.Count == 0 || callParams == null) { throw new ArgumentNullException("handle、linkSiteIds、callParams", "检查参数时发现有空参数。"); } LibHandle libHandle = LibHandleCache.Default.GetCurrentHandle(handle) as LibHandle; if (libHandle == null) { throw new Exception("该账户未登录。"); } callParams.IsCrossSiteCall = true; callParams.UserId = libHandle.UserId; callParams.Token = GetToken(libHandle, 30 * 1000, dataAccess); if (string.IsNullOrEmpty(callParams.Token)) { throw new Exception("获取跨站访问令牌信息失败。"); } Dictionary <string, string> urls = GetSiteUrls(linkSiteIds); if (urls == null || urls.Count == 0) { throw new Exception("查找到的站点Url为空。"); } Dictionary <string, ExecuteBcfMethodResult> dicResults = new Dictionary <string, ExecuteBcfMethodResult>(); string errorInfo = string.Empty; List <Task> tasks = new List <Task>(); foreach (string siteId in urls.Keys) { var url = urls[siteId]; if (string.IsNullOrEmpty(url)) { continue; } url = string.Format("{0}/billSvc/invorkBcf", url); var task = Task.Factory.StartNew(() => { try { var sendObj = new { param = callParams };//参数名必须一致 dynamic ret = LibNetUtils.HttpPostCall <dynamic>(url, sendObj, out errorInfo, callParams.TimeoutMillSecs); if (ret != null) { ExecuteBcfMethodResult result = JsonConvert.DeserializeObject <ExecuteBcfMethodResult>((string)ret.ExecuteBcfMethodResult); lock (dicResults) { dicResults.Add(siteId, result); } } else if (string.IsNullOrEmpty(errorInfo) == false) { ExecuteBcfMethodResult result = new ExecuteBcfMethodResult(); result.Messages.Add(new LibMessage() { MessageKind = LibMessageKind.Error, Message = string.Format("执行跨站请求出现异常:{0}", errorInfo) }); lock (dicResults) { dicResults.Add(siteId, result); } } } catch (Exception exp) { LibCommUtils.AddOutput(@"Error\CrossSiteCall", string.Format("CheckSSOLoginState error:{0}\r\nStacktrace:{1}", exp.Message, exp.StackTrace)); ExecuteBcfMethodResult result = new ExecuteBcfMethodResult(); result.Messages.Add(new LibMessage() { MessageKind = LibMessageKind.Error, Message = string.Format("执行跨站请求出现异常:{0}", exp.Message) }); lock (dicResults) { dicResults.Add(siteId, result); } } }); tasks.Add(task); } //循环检查等待所有task都执行完毕 int waitMillSecs = callParams.TimeoutMillSecs + 1000;//多等一秒 int waitCount = 0; //等待超时时间到来,或者全部已经执行完毕 while (waitCount < waitMillSecs) { bool isAllFinished = tasks.All(t => { return(t.IsCompleted); }); if (isAllFinished) { break; } waitCount += 100; Thread.Sleep(100); } return(dicResults); }