亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ASP.NET MVC4+BootStrap 實戰(三)

發布時間:2020-09-25 17:03:30 來源:網絡 閱讀:2730 作者:BruceAndLee 欄目:編程語言

上節我們剩余Compare和Fix按鈕沒有講,本節我們就來講一下Compare按鈕的功能,年底了,要開年會了,一個個積極的跟邱少云似得,給員工漲工資的時候能不能也積極點。不說了,說多了都是淚。


還記得我之前寫的大數據實戰之環境搭建,我們今天主要是拿DB的數據和solr的數據作比較,得出比較結果。首先,先啟動centOS,啟動tomcat,這樣我們才能利用SolrNet調用solr公開的API。關于solr的啟動再次我就不再贅述。

ASP.NET MVC4+BootStrap 實戰(三)

OK,我們將solr實例啟動起來后,用firefox瀏覽管理界面,沒問題。目前solr中并沒有任何數據。

接下來我們就要看點擊Compare按鈕了,點擊Compare按鈕,Compare按鈕在哪里呢,在Partial頁。

@using Bruce.GRLC.Model.ViewModel;
@model UserInfoViewModel
<div class="col-md-6 form-group">
    <label class="control-label">
        The Same:
    </label>
    <select id="selsamelist" class="form-control" multiple="multiple" >
        @if (Model!=null&&Model.SameWithSolrEntityList != null && Model.SameWithSolrEntityList.Count > 0)
        {
            foreach (var entity in Model.SameWithSolrEntityList)
            {
                <option value="@entity.UserNo">@entity.Name</option>
            }
        }
    </select>
    <input id="btncompare" type="button" class="btn btn-info" value="Compare"  />
</div>
<div class="col-md-6 form-group">
    <label class="control-label">
        The Difference:
    </label>
    <select id="seldifflist" class="form-control" multiple="multiple" >
        @if (Model.DifferenceWithSolrEntityList != null && Model.DifferenceWithSolrEntityList.Count > 0)
        {
            foreach (var entity in Model.DifferenceWithSolrEntityList)
            {
                <option value="@entity.UserNo">@entity.Name</option>
            }
        }
    </select>
    <input type="button" class="btn btn-info" value="Fix"  />
</div>

OK,我們看到了按鈕在這里,我們設置按鈕的樣式為btn btn-info,這都是bootStrap提供的樣式,我們直接拿來用就ok了。這個頁面其實就是循環相同數據的List和不同數據的List,加載到一個可多選的下拉列表。大家注意到multiple="multiple",可以多選。另外"form-control"也是bootStrap提供的樣式,用來裝飾表單元素的樣式。上面的代碼沒有什么,我們主要是看控制器一級一級往下是怎么處理的,我們先看Compare按鈕的click事件。

$("#btncompare").click(function () {
        $("#selsamelist").empty();
        $("#seldifflist").empty();

        $.ajax({
            url: "/Home/GetCompareResult?pam=" + new Date().toTimeString(),
            type: "POST",
            datatype: "Html",
            beforeSend: function () {
                $("#divcompare").show();
            },
            complete: function () {
                $("#divcompare").hide();
            },
            success: function (data) {
                $("#divcompareresult").html(data);
            },
            error: function () {
                alert("比較失敗!");
            }
        });

首先我們先清除兩個多選下拉列表的數據,因為我們這里并不是返回整個Partial頁面來替換,所以我們必須先把兩個多選下拉數據清除掉。OK,我們看一下控制器。

public PartialViewResult GetCompareResult()
        {
            GRLCBiz instance = GRLCBiz.GetInstance();
            instance.CompareDBAndSolr();
            UserInfoViewModel userInfoViewModel = new UserInfoViewModel();
            userInfoViewModel.DifferenceWithSolrEntityList = instance.differenceUserEntityList;
            List<string> differenceUserIDList = userInfoViewModel.DifferenceWithSolrEntityList.Select(d => d.UserNo.Trim()).ToList();

            userInfoViewModel.SameWithSolrEntityList = instance.userEntityList.Where(u => !differenceUserIDList.Contains(u.UserID.Trim()))
                .Select((userDB, userSolr) =>
                {
                    return new UserSolrEntity()
                    {
                        UserNo = userDB.UserID.Trim(),
                        Name = userDB.UserName == null ? string.Empty : userDB.UserName.Trim()
                    };
                }).ToList();

            return PartialView("~/Views/Partial/DiffAndSameWithSolrPartial.cshtml", userInfoViewModel);
        }

其實很簡單,首先我們調用CompareDBAndSolr方法,這個方法是獲取到比較結果的關鍵。那么比較的話,我們怎么比較呢,大家有經驗的同學一定想到多線程。不錯,就是多線程,可是有人要說了,多線程的話,你怎么知道線程都執行完了,因為只有多個線程都執行完了,我們才能拿到最終的比較結果,顯示到頁面上。說到這里,如果你是一個.net4.0以前的用戶,你可能會想到AutoResetEvent。

說到這個AutoResetEvent,它可以有一個初始的狀態,如果是true,則表明是一個終止狀態,反之則是非終止狀態,那么看一下我們的程序。

public void CompareDBAndSolr()
        {
            if (userEntityList == null)
            {
                userEntityList = this.GetAllDBUserList();
            }

            if (userEntityList == null || userEntityList.Count == 0) return;

            int threadCount = 0;
            int totalCount = userEntityList.Count;
            threadCount = totalCount % ConstValues.CONN_ComparePerThread == 0 ? totalCount / ConstValues.CONN_ComparePerThread : totalCount / ConstValues.CONN_ComparePerThread + 1;

            if (threadCount > ConstValues.CONN_CompareThreadCount)
            {
                threadCount = ConstValues.CONN_CompareThreadCount;
            }

            differenceUserEntityList = new List<UserSolrEntity>();
            autoResetEvents = new AutoResetEvent[threadCount];
            for (int i = 0; i < threadCount; i++)
            {
                autoResetEvents[i] = new AutoResetEvent(false);
                ThreadPool.QueueUserWorkItem(new WaitCallback(CompareUserInfoByThread), i);
                Thread.Sleep(ConstValues.CONN_ThreadCreateInterval);
            }

            WaitHandle.WaitAll(this.autoResetEvents);
        }

在這個方法中我們先拿到數據庫的所有用戶的數據

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

然后計算應該使用的線程數。CONN_ComparePerThread配置的是每個線程比較的數據量,所以我們先拿總數據對其進行求余,得到總線程數,然后再判斷如果總線程數大于配置的線程數CONN_CompareThreadCount,則取配置的線程數。因為機器的資源有限,不可能開啟成百上千個線程,那樣CPU資源占用很大,機器肯能會卡死。所以設置最大線程數是必須的。當我們拿到線程數以后,我們實例化一個AutoResetEvent數組,來管理這些線程之間的通信。接下來循環創建AutoResetEvent,設置其初始狀態為非終止。然后將線程要執行的方法加入線程池工作隊列,并傳遞線程編號i作為方法參數。最后這句WaitHandle.WaitAll(this.autoResetEvents);意思是等待所有的線程任務結束(狀態標記為終止狀態)。

我們接下來看CompareUserInfoByThread方法。

private void CompareUserInfoByThread(object userState)
        {
            int threadIndex = (int)userState;

            try
            {
                UserDBEntity[] copyUserDBEntityList = null;
                while (this.movePosition < this.userEntityList.Count)
                {
                    lock (this.userEntityList)
                    {
                        if (this.movePosition >= this.userEntityList.Count)
                        {
                            break;
                        }

                        if (this.movePosition <= this.userEntityList.Count - ConstValues.CONN_ComparePerThread)
                        {
                            copyUserDBEntityList = new UserDBEntity[ConstValues.CONN_ComparePerThread];
                            userEntityList.CopyTo(this.movePosition, copyUserDBEntityList, 0, ConstValues.CONN_ComparePerThread);
                        }
                        else
                        {   //最后幾個,count<CONN_ComparePerThread
                            copyUserDBEntityList = new UserDBEntity[userEntityList.Count - this.movePosition];
                            userEntityList.CopyTo(this.movePosition, copyUserDBEntityList, 0, copyUserDBEntityList.Length);
                        }
                        this.movePosition += ConstValues.CONN_ComparePerThread;
                    }
                    this.CompareUserInfoStart(copyUserDBEntityList, threadIndex);
                }

            }
            catch (Exception ex)
            {
                LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex);
            }
            finally
            {
                this.autoResetEvents[threadIndex].Set();
            }
        }

這個方法其實就是多線程瓜分數據了,每個線程Copy出一批(CONN_ComparePerThread)DB的數據去和solr作對比,每個線程拿到自己的那批數據后,將計數器movePosition增加CONN_ComparePerThread。直到這些線程將這些數據瓜分完,大家注意到在finally語句塊,我們對每個AutoResetEvent對象調用set方法,意思是告訴WaitHandle,我已經執行完了,即終止狀態。這樣當WaitHanlde收到每個線程執行完畢的信號后,結束等待,否則就會一直等待下去,這就是為什么Set方法的調用一定要放到finally塊的原因。OK,繼續看下一個方法CompareUserInfoStart

private void CompareUserInfoStart(UserDBEntity[] userDBEntityList, int threadIndex)
        {
            List<string> userIDList = userDBEntityList.Select(u => u.UserID.Trim()).ToList();
            StringBuilder solrFilter = new StringBuilder();

            foreach (var userID in userIDList)
            {
                solrFilter.Append("UserNo:");
                solrFilter.Append(userID);
                solrFilter.Append(" OR ");
            }

            solrFilter.Length = solrFilter.Length - 4;

            List<UserSolrEntity> userSolrEntityList = SolrHelper.GetInstance().QueryByFilter<UserSolrEntity>(solrFilter.ToString());

            List<UserSolrEntity> userDBConvertSolrEntityList = userDBEntityList.Select((userDB, userSolr) =>
            {
                return new UserSolrEntity()
                {
                    UserNo = userDB.UserID.Trim(),
                    Age = userDB.Age,
                    Name = userDB.UserName.Trim(),
                    IsMarried = userDB.Married == "1"
                };
            }).ToList();

            lock (_lockObj)
            {
                differenceUserEntityList.AddRange(userDBConvertSolrEntityList.Except(userSolrEntityList, new UserSolrEntityCompare()));
            }
        }
    }

我們拿到對比的DB數據實體List之后,得到userID,然后拼成solr的查詢條件solrFilter,然后調用SolrHelper中的QueryByFilter<T>方法去查詢出一個Solr的實體List,然后我們將DB的實體List通過Linq轉化為Solr的實體List userDBConvertSolrEntityList。然后通過Except方法找出不同的實體List,放置到differenceUserEntityList。在這里注意IEqualityCompare接口的實現。

public class UserSolrEntityCompare : IEqualityComparer<UserSolrEntity>
    {
        public bool Equals(UserSolrEntity original, UserSolrEntity destination)
        {
            original.Name = original.Name ?? string.Empty;
            original.UserNo = original.UserNo ?? string.Empty;
            destination.Name = destination.Name ?? string.Empty;
            destination.UserNo = destination.UserNo ?? string.Empty;

            return original.UserNo.Trim().Equals(destination.UserNo.Trim())
                && original.Age == destination.Age
                && original.Name.Trim().Equals(destination.Name.Trim())
                && original.IsMarried == destination.IsMarried;
        }

        public int GetHashCode(UserSolrEntity userSolrEntity)
        {
            return userSolrEntity.UserNo.GetHashCode();
        }
    }

OK,到這里就全部結束了,我們在action中拿到了比較出的結果,然后組成viewModel,返回給Partial頁面去綁定。看一下效果Comparing,please wait......

ASP.NET MVC4+BootStrap 實戰(三)


下面是比較出的結果,因為solr中沒有數據,所以都是不相同的,因為取DB數據是INNER JOIN,所以只有四條數據。

ASP.NET MVC4+BootStrap 實戰(三)

OK,本節到此結束,下節我們看一下Fix功能的實現。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

无为县| 家居| 阿克苏市| 仁寿县| 桂东县| 深州市| 班玛县| 怀化市| 霸州市| 昭觉县| 金平| 蚌埠市| 龙州县| 天津市| 仙游县| 云龙县| 宁城县| 锡林郭勒盟| 顺平县| 建平县| 常山县| 萍乡市| 通化县| 孟连| 阳朔县| 繁昌县| 抚宁县| 贺兰县| 望城县| 盘山县| 泸州市| 建阳市| 两当县| 灵台县| 登封市| 弥勒县| 辽阳县| 仁化县| 铜川市| 交口县| 安福县|