现在呆惯了外企,觉得跳槽出去都没地方去,在外企请假干什么的方便,而且相对轻松,就是money少了点,但是饭也要吃饱啊。
今天要讲的当然是最后一个按钮了,fix按钮。我们看一下js代码
$("#btnfix").click(function () { $.ajax({ url: "/Home/SolrDataFix?pam=" + new Date().toTimeString(), type: "POST", datatype: "Html", beforeSend: function () { $("#divfix").show(); }, complete: function () { $("#divfix").hide(); }, success: function (data) { if (data.IsSuccess) { alert("Fixed successfully!"); } else { alert(data.ErrorMsg); } }, error: function () { alert("Fix失败!"); } }); });
我们fix完成之后会得到一个json格式的数据,我们根据是否成功弹出提示。
接下来我们看看控制器
public JsonResult SolrDataFix() { int suc = GRLCBiz.GetInstance().FixSolrData(); if (suc == 1) { return Json(new { IsSuccess = true }, JsonRequestBehavior.AllowGet); } return Json(new { IsSuccess = false, ErrorMsg = "Fix failed!" }, JsonRequestBehavior.AllowGet); }
在这里,主要是看Biz层的逻辑。其实之前我讲过Compare的时候用多线程,那么fix的时候也必然要使用多线程。不过,这次我们要使用的是.net4以上版本中的Task,看代码
public int FixSolrData() { if (this.differenceUserEntityList == null) return -1; this.movePosition = 0; int threadCount = 0; int totalCount = differenceUserEntityList.Count; threadCount = totalCount % ConstValues.CONN_ComparePerThread == 0 ? totalCount / ConstValues.CONN_ComparePerThread : totalCount / ConstValues.CONN_ComparePerThread + 1; if (threadCount > ConstValues.CONN_FixThreadCount) { threadCount = ConstValues.CONN_FixThreadCount; } taskList = new List<Task<int>>(); for (int i = 0; i < threadCount; i++) { Task<int> task = Task.Factory.StartNew<int>(() => { return SolrDataFixByThread(i); }); taskList.Add(task); } Task.WaitAll(taskList.ToArray()); foreach (var task in taskList) { if (task.Result == -1) return -1; break; } return 1; }
这里也是先计算线程数,然后我们循环开启Task,执行任务,任务是什么呢,就是SolrDataFixByThread方法。这段代码也是等待所有线程结束以后,我去循环结果,发现如果有某一个线程执行失败,我就返回-1。OK,我们看一下SolrDataFixByThread这个方法。
private int SolrDataFixByThread(int threadIndex) { try { string[] copyUserDBIDList = null; while (this.movePosition < this.differenceUserEntityList.Count) { lock (this.differenceUserEntityList) { List<string> userIDList = differenceUserEntityList.Select(d => d.UserNo.Trim()).ToList(); if (this.movePosition >= this.differenceUserEntityList.Count) { break; } if (this.movePosition <= this.userEntityList.Count - ConstValues.CONN_ComparePerThread) { copyUserDBIDList = new string[ConstValues.CONN_ComparePerThread]; userIDList.CopyTo(this.movePosition, copyUserDBIDList, 0, ConstValues.CONN_ComparePerThread); } else { copyUserDBIDList = new string[userEntityList.Count - this.movePosition]; userIDList.CopyTo(this.movePosition, copyUserDBIDList, 0, copyUserDBIDList.Length); } this.movePosition += ConstValues.CONN_ComparePerThread; } return this.SolrDataFixStart(copyUserDBIDList, threadIndex); } return 1; } catch (Exception ex) { LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex); return -1; } }
和Compare方法大同小异,在此就不多说了。我们看SolrDataFixStart方法
private int SolrDataFixStart(string[] userIDList, int threadIndex) { string userIDXml = this.BuildUserIDXml(userIDList); List<UserDBEntity> userDBEntityList = GRLCDAL.GetInstance().GetUserEntityListByIDs(userIDXml); List<UserSolrEntity> userSolrEntityList = userDBEntityList.Select((userDBEntity, userSolrEntity) => { userDBEntity.UserID = userDBEntity.UserID ?? string.Empty; userDBEntity.UserName = userDBEntity.UserName ?? string.Empty; return new UserSolrEntity() { UserNo = userDBEntity.UserID, Age = userDBEntity.Age, IsMarried = userDBEntity.Married == "1", Name = userDBEntity.UserName.Trim() }; }).ToList(); return SolrHelper.GetInstance().AddEntityList(userSolrEntityList.ToList()); }
第一句,BuildUserIDXml,如下
private string BuildUserIDXml(string[] userIDList) { XmlDocument xmlDocument = new XmlDocument(); XmlNode xmlRoot = xmlDocument.CreateElement("UserIDList"); foreach (var userID in userIDList) { XmlElement xmlElement = xmlDocument.CreateElement("UserID"); xmlElement.InnerText = userID; xmlRoot.AppendChild(xmlElement); } return xmlRoot.OuterXml; }
构造了一个很简单的xml格式的数据。然后我们将它传入DAL层的方法GetUserEntityListByIDs
public List<UserDBEntity> GetUserEntityListByIDs(string userIDXml) { string sqlScript = string.Empty; try { sqlScript = DBScriptManager.GetScript(this.GetType(), "GetUserInfoByIDs"); SqlParameter[] sqlParameters = { new SqlParameter("@UserIDXml",SqlDbType.Xml) }; sqlParameters[0].Value = userIDXml; DataSet ds = SqlHelper.ExecuteDataset(ConstValues.CON_DBConnection, CommandType.Text, sqlScript, sqlParameters); if (ds != null && ds.Tables.Count > 0) { return ds.Tables[0].ToEntityList<UserDBEntity>(); } return new List<UserDBEntity>(); } catch (Exception ex) { LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex); return null; } }
没什么可说的,大家注意,这里这个参数是xml类型的,在SqlServer中,当我们要传递一批数据进行更新时,往往是传入一个实体List进行更新,就可以采用xml的方式传入SP,进行批量处理。OK,我们看一下这个脚本
;WITH UserIDList AS ( SELECT U.C.value(N‘(text())[1]‘,‘CHAR(25)‘) AS UserID FROM @UserIDXml.nodes(N‘UserIDList/UserID‘) AS U(C) ) SELECT A.UseNo, ISNULL(B.Name,‘‘) AS Name, ISNULL(B.Age,0) AS Age, ISNULL(B.Temper,‘‘) AS Married FROM Bonus.dbo.[User] A WITH(NOLOCK) INNER JOIN Bonus.dbo.UerInfo B WITH(NOLOCK) ON A.UseNo = B.UseNo WHERE EXISTS( SELECT TOP 1 1 FROM UserIDList C WHERE C.UserID = A.UseNo )
第一句先解析出数据放入一个临时表UserIDList,大家注意这个临时表只能在紧跟着的后面的语句中使用,而且只能使用一次就销毁了。ok,通过这个脚本,我们就拿到了要同步到Solr的数据,开始同步
同步完成之后,我们看一下Solr数据,linux中的火狐浏览器没有样式
我们还是通过windows浏览
OK,Fix一部分数据之后,对比变成下面的样子
OK,今天就到这里,以后会换个系统讲解。