基本上一看就明白了,控制器調用Biz層,Biz層調用DAL層,DAL層進行數據的CURD。Utility是一些公用的類庫。ok,爲何程序集的命名都是以Bruce開頭呢,由於我在公司的英文名叫這個。廢話很少說,咱們先看一下頁面前端
咱們引入了BootStrap,主要是爲了頁面佈局。在Views中Partial下面放的都是部分頁。html5
咱們先看一下運行效果,今天主要是講頁面初始化部分。jquery
其實查詢條件就是婚否,出生日期,姓名的模糊查詢。咱們先看一下頁面Index.cshtml的代碼web
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width;initial-scale=1" />
- <title>Compare data between Solr and DB</title>
- <link rel="stylesheet" type="text/css" href="~/BootStrap/css/bootstrap-theme.css" />
- <link rel="stylesheet" type="text/css" href="~/BootStrap/css/bootstrap.css" />
- @*@Styles.Render("~/css")*@
- @Scripts.Render("~/bundles/BootStrap")
- @Scripts.Render("~/bundles/Scripts")
- <style type="text/css">
- .pre-Scrollable {
- max-height: 700px;
- overflow-y: scroll;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <form id="formsync">
- <div class="row">
- <div class="col-md-12">
- <h1 style="color:red"><b>Compare Data Between Solr and DB</b></h1>
- </div>
- </div>
- <div class="row" id="divloding" style="display:none;text-align:center">
- <div class="col-md-6">
- <img src="~/Images/ajaxLoading.gif" alt="load failed" />
- <label>getting,please wait......</label>
- </div>
- </div>
- <div class="row" id="divcompare" style="display:none;text-align:center">
- <div class="col-md-6">
- <img src="~/Images/ajaxLoading.gif" alt="load failed" />
- <label>comparing,please wait......</label>
- </div>
- </div>
- <div class="row" id="divfix" style="display:none;text-align:center">
- <div class="col-md-6">
- <img src="~/Images/ajaxLoading.gif" alt="load failed" />
- <label>fixing,please wait......</label>
- </div>
- </div>
- <div class="row" style="margin-top:10px">
- <div class="col-md-12 form-inline">
- <div class="form-group input-group">
- <span class="input-group-addon">IsMarried:</span>
- @Html.DropDownList("ddlMarried", ViewBag.MarriedList as SelectList, null, new { id = "ddlMarried", @class = "form-control" })
- </div>
- <div class="form-group" style="margin-left:10px">
- <label class="control-label">BirthDay:</label>
- <input type="date" id="txtdatestart" class="form-control">
- <label class="control-label">-</label>
- <input type="date" id="txtdateend" class="form-control">
- </div>
- <div class="form-group input-group" style="margin-left:10px">
- <span class="input-group-addon">Name:</span>
- <input id="txtusername" type="text" class="form-control" placeholder="input name..." style="width:120px" />
- </div>
- <div class="form-group" style="margin-left:10px">
- <input id="btnsearch" type="button" class="btn btn-info" value="Get" style="width:70px" />
- </div>
- </div>
- </div>
- <div class="row" style="margin-top:10px">
- <div id="divresult" class="col-md-7 form-inline pre-Scrollable">
- @{Html.RenderPartial("~/Views/Partial/UserInfoPartial.cshtml");}
- </div>
- <div class="col-md-5">
- @{Html.RenderPartial("~/Views/Partial/DiffAndSameWithSolrPartial.cshtml");}
- </div>
- </div>
- </form>
- </div>
- </body>
- </html>
咱們使用html5+BootStrap佈局,這裏用到了BootStrap的網格系統,將瀏覽器平分爲12份,即12列,很容易構造出響應式佈局系統。那麼什麼是BootStrap的網格系統,看以下的解釋ajax
![ASP.NET MVC4+BootStrap實戰](http://static.javashuo.com/static/loading.gif)
OK,咱們怎麼看是不是響應式的佈局呢,咱們打開谷歌瀏覽器,現將瀏覽器縮小到必定程度。sql
看到了吧,即便設備瀏覽器這麼小,咱們仍是能用。那咱們在手機模擬器中測試一下,打開谷歌瀏覽器,按F12,點擊手機模擬器樣的東西,而後Device選擇iphone6。 bootstrap
![ASP.NET MVC4+BootStrap實戰](http://static.javashuo.com/static/loading.gif)
咱們看到iphone6下面的效果是這樣的。說到這裏我最近很討厭兩個廣告,一個是「這個是iphone6,這個是iphone6 plus,它們都有一個叫健康的東西.....可是好吃啊」,還有一個是「當牛魔王變成一個餃子,我願意變成一雙筷子」。看到這兩個廣告,我想砸電視。瀏覽器
那爲何不一樣的設備不一樣的瀏覽器都是能夠正常瀏覽的呢,緣由就在於這段代碼
- <meta name="viewport" content="width=device-width;initial-scale=1" />
這段代碼的意思是網頁寬度默認等於屏幕寬度,縮放比例默認爲1(網頁初始比例佔屏幕的100%)。
ok,咱們接下來看head部分css和js的引用,這裏有個新東西叫Bundle,用來打包壓縮js或者css的。經過它打包壓縮的js或者css客戶端只須要下載一次包便可,並且能夠在客戶端緩存起來,當檢測到有更新時,纔會從新下載。
下面是Bundle.cs的代碼
- using System.Web;
- using System.Web.Optimization;
- namespace Brue.GRLC.Web
- {
- public class BundleConfig
- {
- // 有關 Bundling 的詳細信息,請訪問 http://go.microsoft.com/fwlink/?LinkId=254725
- public static void RegisterBundles(BundleCollection bundles)
- {
- bundles.Add(new ScriptBundle("~/bundles/BootStrap").Include(
- "~/Scripts/jquery-1.11.1.js","~/BootStrap/js/bootstrap.js"));
- bundles.Add(new ScriptBundle("~/bundles/Scripts").Include("~/Js/Index.js"));
- bundles.Add(new StyleBundle("~/css").Include("~/BootStrap/css/bootstrap-theme.css"
- , "~/BootStrap/css/bootstrap.css"));
- }
- }
- }
注意,在這裏引用js的時候不要引用壓縮過的js,好比xxx.min.js。當Bundle在遇到這種js命名文件的時候,直接就忽略掉了。那麼咱們在Head中只須要使用以下代碼來引用便可。
- @Scripts.Render("~/bundles/BootStrap")
- @Scripts.Render("~/bundles/Scripts")
OK,在這我碰到一個問題,就是個人css經過這種方式引用,始終提示Index out of range。若是哪位大牛知道緣由的話麻煩留個言,謝謝!
OK,咱們接下來看一下控制器代碼,頁面剛進來,會走Home/Index。
- public ActionResult Index()
- {
- List<object> marriedList = GRLCBiz.GetInstance().GetMarriedList();
- SelectList selectList = new SelectList(marriedList, "MarriedID", "DisplayContent", "-1");
- ViewBag.MarriedList = selectList;
- DataResponse<UserDBEntity> dataResponse = GRLCBiz.GetInstance().GetUserInfoEntityList();
- UserInfoViewModel userInfoViewModel = new UserInfoViewModel();
- userInfoViewModel.DataResponse = dataResponse;
- userInfoViewModel.DataResponse.PageIndex = ConstValues.CONN_DefaultPageIndex;
- userInfoViewModel.DataResponse.PageSize = ConstValues.CONN_DefaultPageSize;
- userInfoViewModel.DataResponse.StartPageIndex = 1;
- return View(userInfoViewModel);
- }
首先咱們構造了一個SelectList用於下拉列表,Biz層的代碼很簡單
- public dynamic GetMarriedList()
- {
- IList<object> marriedList = new List<object>();
- marriedList.Add(new { MarriedID = -1, DisplayContent = "No Selection" });
- marriedList.Add(new { MarriedID = 0, DisplayContent = "Married" });
- marriedList.Add(new { MarriedID = 1, DisplayContent = "UnMarried" });
- return marriedList;
- }
用匿名類去構造一個List。接下來就是DataReponse的獲取,Biz層的代碼以下
- public DataResponse<UserDBEntity> GetUserInfoEntityList(UserInfoRequest request = null)
- {
- if(request==null)
- {
- request = new UserInfoRequest();
- request.PageIndex = ConstValues.CONN_DefaultPageIndex;
- request.PageSize = ConstValues.CONN_DefaultPageSize;
- }
- int totalCount=0;
- List<UserDBEntity> userDBEntityList = GRLCDAL.GetInstance().GetUserInfoEntityList(request, out totalCount);
- DataResponse<UserDBEntity> dataResponse = new DataResponse<UserDBEntity>();
- dataResponse.DataList = userDBEntityList;
- dataResponse.TotalCount = totalCount;
- return dataResponse;
- }
沒什麼可說的,ConstValues類中是一些靜態只讀屬性
- public class ConstValues
- {
- public static readonly string CON_DBConnection = ConfigurationManager.ConnectionStrings["DB_ConnectionStr"].ToString();
- public static readonly string CON_DbScriptXmlFolder = ConfigurationManager.AppSettings["DbScriptXmlFolder"];
- public static readonly int CONN_DefaultPageSize = int.Parse(ConfigurationManager.AppSettings["DefaultPageSize"]);
- public static readonly int CONN_DefaultPageIndex = 1;
- public static readonly int CONN_PagerDisplayCount = int.Parse(ConfigurationManager.AppSettings["PagerDisplayCount"]);
- }
看一下DAL層。
- public List<UserDBEntity> GetUserInfoEntityList(UserInfoRequest request, out int totalCount)
- {
- totalCount = 0;
- string sqlScript = string.Empty;
- try
- {
- sqlScript = DBScriptManager.GetScript(this.GetType(), "GetUserInfo");
- SqlParameter[] sqlParameters =
- {
- new SqlParameter("@IsMarried",SqlDbType.Char,1),
- new SqlParameter("@StartDate",SqlDbType.DateTime),
- new SqlParameter("@EndDate",SqlDbType.DateTime),
- new SqlParameter("@UserName",SqlDbType.NVarChar,20),
- new SqlParameter("@PageIndex",SqlDbType.Int),
- new SqlParameter("@PageSize",SqlDbType.Int),
- new SqlParameter("@TotalCount",SqlDbType.Int)
- };
- sqlParameters[0].Value = request.IsMarried;
- sqlParameters[1].Value = request.StartDate;
- sqlParameters[2].Value = request.EndDate;
- sqlParameters[3].Value = request.UserName;
- sqlParameters[4].Value = request.PageIndex;
- sqlParameters[5].Value = request.PageSize;
- sqlParameters[6].Direction = ParameterDirection.Output;
- DataSet ds = SqlHelper.ExecuteDataset(ConstValues.CON_DBConnection, CommandType.Text, sqlScript, sqlParameters);
- if (ds != null && ds.Tables.Count > 0)
- {
- totalCount = Convert.ToInt32(sqlParameters[6].Value);
- return ds.Tables[0].ToEntityList<UserDBEntity>();
- }
- return new List<UserDBEntity>();
- }
- catch (Exception ex)
- {
- LogHelper.WriteExceptionLog(MethodBase.GetCurrentMethod(), ex);
- return null;
- }
- }
OK,咱們看一下這個GetUserInfo腳本,在Bruce.GRLC.DbScriptXml程序集下。
- <?xml version="1.0" encoding="utf-8" ?>
- <Scripts>
- <Script Key="GetUserInfo">
- <![CDATA[
- DECLARE @UserTempTable TABLE
- (
- ID INT IDENTITY(1,1) NOT NULL,
- UserNo CHAR(25) NOT NULL
- )
- INSERT INTO @UserTempTable
- (
- UserNo
- )
- SELECT
- A.UseNo
- FROM Bonus.dbo.[User] A WITH(NOLOCK)
- LEFT JOIN Bonus.dbo.UerInfo B WITH(NOLOCK)
- ON A.UseNo = B.UseNo
- WHERE (@IsMarried IS NULL OR @IsMarried = '' OR B.Temper = @IsMarried)
- AND
- (
- @StartDate IS NULL
- OR @EndDate IS NULL
- OR B.BirthDay BETWEEN @StartDate AND @EndDate
- )
- AND
- (
- @UserName IS NULL
- OR @UserName = ''
- OR B.Name LIKE '%' + @UserName + '%'
- )
- ORDER BY A.UseNo ASC
- SELECT @TotalCount = COUNT(1) FROM @UserTempTable
- SELECT
- UseNo,
- Name,
- Age,
- Married
- FROM(
- SELECT
- ID = ROW_NUMBER() OVER(ORDER BY UseNo ASC),
- A.UseNo,
- B.Name,
- B.Age,
- Married = CASE WHEN B.Temper = '1'
- THEN '已婚'
- ELSE '未婚'
- END
- FROM Bonus.dbo.[User] A WITH(NOLOCK)
- LEFT JOIN Bonus.dbo.UerInfo B WITH(NOLOCK)
- ON A.UseNo = B.UseNo
- INNER JOIN @UserTempTable C
- ON C.UserNo = A.UseNo
- ) N
- WHERE ID BETWEEN (@PageIndex - 1)* @PageSize + 1 AND @PageIndex * @PageSize
- ]]>
- </Script>
- </Scripts>
腳本很簡單,就是傳入參數查分頁數據。
在DAL層咱們將DataTable經過ToEntityList轉化爲了實體List,在Utility中咱們定義了一個擴展用來轉化。
- public static class DataTableToEntityExtension
- {
- public static List<T> ToEntityList<T>(this DataTable dt) where T : class,new()
- {
- List<T> entityList = new List<T>();
- Type entityType = typeof(T);
- PropertyInfo[] propertys = entityType.GetProperties();
- DataMappingAttribute mappingAttribute = null;
- foreach (DataRow dr in dt.Rows)
- {
- T tEntity = new T();
- foreach (PropertyInfo pi in propertys)
- {
- mappingAttribute = pi.GetCustomAttribute(typeof(DataMappingAttribute)) as DataMappingAttribute;
- if (mappingAttribute != null && dt.Columns.Contains(mappingAttribute.mappingName))
- {
- if (!pi.CanWrite) continue;
- object value = dr[mappingAttribute.mappingName];
- if (value != DBNull.Value)
- pi.SetValue(tEntity, value, null);
- }
- }
- entityList.Add(tEntity);
- }
- return entityList;
- }
- }
值那麼轉化的時候是怎麼讓DataTable的列和實體匹配起來,你能夠將列別名和實體定義成同樣的,還有一種你可使用Attribute。那咱們使用後者,由於後者更靈活。
- [AttributeUsage(AttributeTargets.Property)]
- public class DataMappingAttribute : Attribute
- {
- public string mappingName;
- public DbType dbType;
- public DataMappingAttribute()
- { }
- public DataMappingAttribute(string mappingName, DbType dbType)
- {
- this.mappingName = mappingName;
- this.dbType = dbType;
- }
- }
定義好Attribute以後,咱們設置其能使用的目標只能是Property。而後咱們在實體類裏面的屬性上加上這個Attribute。
- namespace Bruce.GRLC.Model.Entity
- {
- public class UserDBEntity
- {
- [DataMapping("UseNo", DbType.AnsiString)]
- public string UserID { get; set; }
- [DataMapping("Name", DbType.AnsiString)]
- public string UserName { get; set; }
- [DataMapping("Age", DbType.Int32)]
- public int Age { get; set; }
- [DataMapping("Married", DbType.String)]
- public string Married { get; set; }
- }
- }
在DataTableToEntityExtension這個擴展中咱們獲得屬性的Attribute去和DataTable的列名去匹配,反射賦值。
OK,拿到數據後,咱們在控制器構造viewModel,傳遞給界面來綁定。咱們看一下部分頁UserInfoPartial.cshtml的代碼
- @using Bruce.GRLC.Model.ViewModel;
- @model UserInfoViewModel
- <table id="tabuserinfo" class="table table-bordered table-hover">
- <thead>
- <tr style="background-color: #2aabd2;color:white">
- <th>賬號</th>
- <th>姓名</th>
- <th>年齡</th>
- <th>婚否</th>
- </tr>
- </thead>
- <tbody>
- @if (Model != null && Model.DataResponse != null && Model.DataResponse.DataList != null)
- {
- foreach (var userEntity in Model.DataResponse.DataList)
- {
- <tr>
- <td>
- @userEntity.UserID
- </td>
- <td>
- @userEntity.UserName
- </td>
- <td>
- @userEntity.Age
- </td>
- <td>
- @userEntity.Married
- </td>
- </tr>
- }
- }
- </tbody>
- </table>
- <div id="divpagination">
- @{Html.RenderPartial("~/Views/Partial/PaginationPartial.cshtml", Model.DataResponse);}
- </div>
其實也就是一個應用了BoootStrap樣式的表格,有邊框和鼠標通過的樣式。關於BootStrap的樣式的使用,請參考BootStrap官網。代碼很簡單,就是循環遍歷,展現數據。