模型原型:服務器的配置和運行狀態信息。css
設計要求:Json格式數據解析後,判斷配置信息是不是新數據或者是否更新。如是新數據,則直接添加到數據庫;如果數據更新,則更新數據庫配置信息並更新運行狀態信息;都不是則僅將運行狀態添加到數據庫。最後從數據庫取數據並展現。html
模型難點:每一個服務器會搭載多個網卡和最多44個硬盤。jquery
(1)View層如何同時展現全部硬盤和其餘設備屬性的信息。數據庫
(2)單服務器配多網卡多硬盤一定會設計多個表(即服務器配置表、運行狀態表、網卡配置表、硬盤配置表),MVC框架下如何同時將其Model傳到View層。json
(3)本文程序使用PageList進行分頁,一般爲了程序運行速度,會在查詢時進行分頁,及var servers = db.Servers.OrderByDescending(e => e.ID).ToPagedList(pageNumber, 7),但本設計考慮到多Model傳到View層,此方法不適用。如何使程序適應上萬條數據的數據庫。bootstrap
Model層:服務器
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.ComponentModel.DataAnnotations; 5 using System.Linq; 6 using System.Web; 7 8 namespace monitoring.Models 9 { 10 public class Servers 11 { 12 public int ID { get; set; } 13 [Required] 14 [DisplayName("主板序列號")] 15 public string AMDCDkey { get; set; } 16 [Required] 17 [DisplayName("服務器名")] 18 public string HostName { get; set; } 19 [Required] 20 [DisplayName("CPU型號")] 21 public string CPUType { get; set; } 22 [Required] 23 [DisplayName("CPU數量")] 24 public int CPUNum { get; set; } 25 [Required] 26 [DisplayName("內存大小")] 27 public string RAMSize { get; set; } 28 [DisplayName("Raid卡型號")] 29 public string RaidType { get; set; } 30 [Required] 31 [DisplayName("硬盤個數")] 32 public int HDDNum { get; set; } 33 [Required] 34 [DisplayName("機箱型號")] 35 public string CaseType { get; set; } 36 } 37 }
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.ComponentModel.DataAnnotations; 5 using System.Linq; 6 using System.Web; 7 8 namespace monitoring.Models 9 { 10 public class Servers 11 { 12 public int ID { get; set; } 13 [Required] 14 [DisplayName("主板序列號")] 15 public string AMDCDkey { get; set; } 16 [Required] 17 [DisplayName("服務器名")] 18 public string HostName { get; set; } 19 [Required] 20 [DisplayName("CPU型號")] 21 public string CPUType { get; set; } 22 [Required] 23 [DisplayName("CPU數量")] 24 public int CPUNum { get; set; } 25 [Required] 26 [DisplayName("內存大小")] 27 public string RAMSize { get; set; } 28 [DisplayName("Raid卡型號")] 29 public string RaidType { get; set; } 30 [Required] 31 [DisplayName("硬盤個數")] 32 public int HDDNum { get; set; } 33 [Required] 34 [DisplayName("機箱型號")] 35 public string CaseType { get; set; } 36 } 37 }
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.ComponentModel.DataAnnotations; 5 using System.Linq; 6 using System.Web; 7 8 namespace monitoring.Models 9 { 10 public class NIC 11 { 12 public int ID { get; set; } 13 public string AMDCDkey { get; set; } 14 [Required] 15 [DisplayName("網卡型號")] 16 public string NICType { get; set; } 17 [Required] 18 [DisplayName("網卡數量")] 19 public int NICNum { get; set; } 20 } 21 }
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.ComponentModel.DataAnnotations; 5 using System.Linq; 6 using System.Web; 7 8 namespace monitoring.Models 9 { 10 public class HDD 11 { 12 public int ID { get; set; } 13 public string AMDCDkey { get; set; } 14 public int RootHDD { get; set; } 15 [Required] 16 [DisplayName("硬盤標識")] 17 public string HDDID { get; set; } 18 [Required] 19 [DisplayName("硬盤型號")] 20 public string HDDType { get; set; } 21 [Required] 22 [DisplayName("硬盤容量")] 23 public string HDDCap { get; set; } 24 } 25 }
爲了將多Model傳到View層,單獨創建一個List,將多個model的信息添加到List中。架構
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 namespace monitoring.Models 7 { 8 public class ViewModel 9 { 10 public int ID { get; set; } 11 public Servers SView { get; set; } 12 public ServersUsing SUView { get; set; } 13 public List<NIC> NICView { get; set; } 14 public List<HDD> HDDView { get; set; } 15 } 16 }
如需實現,還要有上下文:框架
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 using System.Data.Entity; 2 3 namespace monitoring.Models 4 { 5 public class ServersContext : DbContext 6 { 7 // 您能夠向此文件中添加自定義代碼。更改不會被覆蓋。 8 // 9 // 若是您但願只要更改模型架構,Entity Framework 10 // 就會自動刪除並從新生成數據庫,則將如下 11 // 代碼添加到 Global.asax 文件中的 Application_Start 方法。 12 // 注意: 這將在每次更改模型時銷燬並從新建立數據庫。 13 // 14 // System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<monitoring.Models.ServersContext>()); 15 16 public ServersContext() : base("name=ServersContext") 17 { 18 19 } 20 21 public DbSet<Servers> Servers { get; set; } 22 public DbSet<ServersUsing> ServersUsings { get; set; } 23 public DbSet<NIC> NICs { get; set; } 24 public DbSet<HDD> HDDs { get; set; } 25 } 26 }
Controller層:ide
實現瞭解析Json並添加數據庫的方法,實現了查詢和分頁功能,完成了將多Model傳到View層的方法。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using System.Data.Entity; 5 using System.Linq; 6 using System.Web; 7 using System.Web.Mvc; 8 using monitoring.Models; 9 using Newtonsoft.Json.Linq; 10 using Newtonsoft.Json; 11 using System.IO; 12 using monitoring.Controllers; 13 using System.Web.Script.Serialization; 14 using PagedList; 15 16 namespace monitoring.Controllers 17 { 18 public class ServersController : Controller 19 { 20 private ServersContext db = new ServersContext(); 21 public void ParseJson(StreamReader reader) 22 { 23 // 配置信息 24 JToken jobject = JToken.ReadFrom(new JsonTextReader(reader)); 25 string jsonText = jobject.ToString(); 26 JObject roots = (JObject)JsonConvert.DeserializeObject(jsonText); 27 JArray servers = (JArray)roots["Servers"]; 28 for (int i = 0; i < servers.Count; i++) 29 { 30 JObject root = (JObject)servers[i]; 31 Servers newdate = new Servers(); 32 newdate.AMDCDkey = (string)root["AMDCDkey"]; 33 newdate.HostName = (string)root["HostName"]; 34 newdate.CPUType = (string)root["CPUType"]; 35 newdate.CPUNum = (int)root["CPUNum"]; 36 newdate.RAMSize = (string)root["RAMSize"]; 37 newdate.RaidType = (string)root["RaidType"]; 38 newdate.HDDNum = (int)root["HDDNum"]; 39 newdate.CaseType = (string)root["CaseType"]; 40 bool NewDate = false; 41 try 42 { 43 var server = db.Servers.Single(x => x.AMDCDkey == newdate.AMDCDkey); 44 if (server != newdate) 45 { 46 server = newdate; 47 UpdateModel<Servers>(newdate); 48 db.SaveChanges(); 49 } 50 } 51 catch 52 { 53 NewDate = true; 54 db.Servers.Add(newdate); 55 db.SaveChanges(); 56 } 57 58 // 運行狀態信息 59 ServersUsing newdateusi = new ServersUsing(); 60 newdateusi.AMDCDkey = (string)root["AMDCDkey"]; 61 newdateusi.CPUUsRate = (string)root["CPUUsRate"]; 62 newdateusi.RAMUsRate = (string)root["RAMUsRate"]; 63 newdateusi.HDDUsRate = (string)root["HDDUsRate"]; 64 newdateusi.HDDIO = (string)root["HDDIO"]; 65 newdateusi.HostcomputerLoad = (string)root["HostcomputerLoad"]; 66 newdateusi.TheRootPartitionUsageRate = (string)root["TheRootPartitionUsageRate"]; 67 newdateusi.Time = DateTime.Now; 68 db.ServersUsings.Add(newdateusi); 69 db.SaveChanges(); 70 71 // 網卡信息 72 JArray NICs = (JArray)root["NIC"]; 73 if (NewDate == true) 74 { 75 for (int b = 0; b < NICs.Count; b++) 76 { 77 JObject nics = (JObject)NICs[b]; 78 NIC newdatenic = new NIC(); 79 newdatenic.AMDCDkey = (string)root["AMDCDkey"]; 80 newdatenic.NICType = (string)nics["NICType"]; 81 newdatenic.NICNum = (int)nics["NICNum"]; 82 db.NICs.Add(newdatenic); 83 db.SaveChanges(); 84 } 85 } 86 else 87 { 88 JavaScriptSerializer Serializer = new JavaScriptSerializer(); 89 List<NIC> objs = Serializer.Deserialize<List<NIC>>(NICs.ToString()); 90 List<NIC> nic = db.NICs.Where(x => x.AMDCDkey == newdate.AMDCDkey).ToList(); 91 bool b = false; 92 foreach (var a in nic) { if (!objs.Contains(a)) b = true; } 93 if (b && nic.Count != objs.Count) 94 { 95 var remove = db.NICs.Where(x => x.AMDCDkey == newdate.AMDCDkey); 96 foreach (var a in remove) 97 { 98 db.NICs.Remove(a); 99 } 100 for (int d = 0; d < NICs.Count; d++) 101 { 102 JObject nics = (JObject)NICs[d]; 103 NIC newdatenic = new NIC(); 104 newdatenic.AMDCDkey = (string)root["AMDCDkey"]; 105 newdatenic.NICType = (string)nics["NICType"]; 106 newdatenic.NICNum = (int)nics["NICNum"]; 107 db.NICs.Add(newdatenic); 108 } 109 db.SaveChanges(); 110 } 111 } 112 113 // 硬盤信息 114 JArray HDDs = (JArray)root["HDD"]; 115 116 if (NewDate == true) 117 { 118 for (int f = 0; f < HDDs.Count; f++) 119 { 120 JObject hdds = (JObject)HDDs[f]; 121 HDD newdatehdd = new HDD(); 122 newdatehdd.HDDID = (string)hdds["HDDID"]; 123 newdatehdd.RootHDD = (int)hdds["RootHDD"]; 124 newdatehdd.AMDCDkey = (string)root["AMDCDkey"]; 125 newdatehdd.HDDType = (string)hdds["HDDType"]; 126 newdatehdd.HDDCap = (string)hdds["HDDCap"]; 127 db.HDDs.Add(newdatehdd); 128 db.SaveChanges(); 129 } 130 } 131 else 132 { 133 JavaScriptSerializer Serializer = new JavaScriptSerializer(); 134 List<HDD> objs = Serializer.Deserialize<List<HDD>>(HDDs.ToString()); 135 List<HDD> hdd = db.HDDs.Where(x => x.AMDCDkey == newdate.AMDCDkey).ToList(); 136 bool b = false; 137 foreach (var a in hdd) { if (!objs.Contains(a)) b = true; } 138 if (b && hdd.Count != objs.Count) 139 { 140 var remove = db.HDDs.Where(x => x.AMDCDkey == newdate.AMDCDkey); 141 foreach (var a in remove) 142 { 143 db.HDDs.Remove(a); 144 } 145 for (int f = 0; f < HDDs.Count; f++) 146 { 147 JObject hdds = (JObject)HDDs[f]; 148 HDD newdatehdd = new HDD(); 149 newdatehdd.HDDID = (string)hdds["HDDID"]; 150 newdatehdd.RootHDD = (int)hdds["RootHDD"]; 151 newdatehdd.AMDCDkey = (string)root["AMDCDkey"]; 152 newdatehdd.HDDType = (string)hdds["HDDType"]; 153 newdatehdd.HDDCap = (string)hdds["HDDCap"]; 154 db.HDDs.Add(newdatehdd); 155 } 156 db.SaveChanges(); 157 } 158 } 159 } 160 } 161 public ActionResult Index(string searchString, int? page) 162 { 163 // 遍歷文件夾中的文件 164 //string path = "C:\\Users\\edong\\Desktop\\json"; 165 //DirectoryInfo dir = new DirectoryInfo(path); 166 //FileInfo[] fil = dir.GetFiles(); 167 //foreach (FileInfo f in fil) 168 //{ 169 // using (StreamReader reader = System.IO.File.OpenText("" + f.FullName + "")) 170 // { 171 // ParseJson(reader); 172 // } 173 // // 存入數據庫後刪除json文件 174 // // System.IO.File.Delete(@""+ f.FullName +""); 175 //} 176 int pageNumber = page ?? 1; 177 178 var servers = db.Servers.OrderByDescending(e => e.ID); 179 180 var listallview = new List<ViewModel>(); 181 foreach (var s in servers) 182 { 183 listallview.Add(new ViewModel() 184 { 185 SView = s, 186 SUView = db.ServersUsings.Where(o => o.AMDCDkey == s.AMDCDkey).First(), 187 NICView = db.NICs.Where(o => o.AMDCDkey == s.AMDCDkey).ToList(), 188 HDDView = db.HDDs.Where(o => o.AMDCDkey == s.AMDCDkey).ToList() 189 }); 190 } 191 var pagelist = listallview.OrderByDescending(e => e.ID).ToPagedList(pageNumber, 7); 192 // 查詢 193 if (!string.IsNullOrEmpty(searchString)) 194 { 195 pagelist = listallview.Where(s => s.SView.HostName.Contains(searchString)).ToPagedList(pageNumber, 7); 196 } 197 // 服務器網卡/硬盤數量最大值 198 int NICNum = 0; 199 int HDDNum = 0; 200 foreach (var item in pagelist) 201 { 202 if (NICNum < item.NICView.Count) 203 NICNum = item.NICView.Count; 204 if (HDDNum < item.HDDView.Count) 205 HDDNum = item.HDDView.Count; 206 } 207 ViewBag.NICNum = NICNum; 208 ViewBag.HDDNum = HDDNum; 209 210 return View(pagelist); 211 } 212 213 protected override void Dispose(bool disposing) 214 { 215 db.Dispose(); 216 base.Dispose(disposing); 217 } 218 } 219 }
View層:
爲了方便查看View和Controller中的傳值等問題,先貼代碼再貼圖。(View中引用了Bootstrap,UI同事教了我一點,僅做排版使用。)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
1 @using monitoring.Models; 2 @using PagedList.Mvc; 3 4 @model PagedList.PagedList<ViewModel> 5 6 @{ 7 ViewBag.Title = "Index"; 8 } 9 <!DOCTYPE html> 10 <head> 11 <title>服務器設備配置信息</title> 12 @*自動刷新,間隔10s*@ 13 @*<meta http-equiv="REFRESH" content="10">*@ 14 <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> 15 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 16 17 <!-- 可選的 Bootstrap 主題文件(通常不用引入) --> 18 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> 19 <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> 20 21 <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> 22 <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> 23 </head> 24 <style type="text/css"> 25 .Menu { 26 float: left; 27 background: #ffffff; 28 } 29 30 .Menu li { 31 margin: 30px 40px 30px 0px; 32 list-style: none; 33 text-align: center; 34 } 35 36 .Table { 37 background: #4ba54b; 38 color: #ffffff; 39 border-radius: 50px; 40 } 41 42 .Date { 43 background: #ffffff; 44 width: 1150px; 45 float: left; 46 margin: 0px 0px 10px 20px; 47 } 48 49 .Date ul { 50 width: 160px; 51 float: left; 52 } 53 54 .Date ul li { 55 margin: 30px 0px 30px 0px; 56 text-align: center; 57 list-style: none; 58 } 59 60 .Text { 61 width: 378px; 62 height: 40px; 63 float: left; 64 margin: 12px 0px 0px 5px; 65 background: #efefef; 66 padding-left: 15px; 67 border-radius: 42px; 68 border: 2px solid #efefef; 69 outline: none; 70 position: absolute; 71 } 72 73 .search { 74 position: absolute; 75 top: 0; 76 right: 0; 77 width: 42px; 78 height: 42px; 79 background: none; 80 border: none; 81 right: 0; 82 margin-top: 12px; 83 } 84 </style> 85 <body style="background:#efefef"> 86 <div style="width:1500px"> 87 <div style="margin: 30px 0px 0px 60px; box-shadow: #ff0000 0px 0px 10px; "> 88 <ul class="Menu"> 89 <li class="Table">配置</li> 90 <li>主機名</li> 91 <li>CPU型號</li> 92 <li>CPU數量</li> 93 <li>內存大小</li> 94 <li>Raid卡型號</li> 95 <li>硬盤個數</li> 96 <li>機箱型號</li> 97 <li class="Table">運行狀態</li> 98 <li>CPU使用率</li> 99 <li>內存使用率</li> 100 <li>硬盤使用率</li> 101 <li>硬盤I/O</li> 102 <li>主機負載</li> 103 <li>根分區使用率</li> 104 <li>時間</li> 105 <li class="Table">網卡信息</li> 106 @for (int i = 0; i < ViewBag.NICNum; i++) 107 { 108 <li>網卡型號</li> 109 <li>網卡數量</li> 110 } 111 <li class="Table">硬盤信息</li> 112 <li>根硬盤型號</li> 113 <li>根硬盤容量</li> 114 @for (int i = 1; i < ViewBag.HDDNum; i++) 115 { 116 <li>硬盤型號</li> 117 <li>硬盤容量</li> 118 } 119 </ul> 120 </div> 121 <div class="Date clearfix" style="height:65px"> 122 @using (Html.BeginForm("Index", "Servers", FormMethod.Get)) 123 { 124 <div class="row"> 125 <div class="col-sm-4" style="float:left"> 126 <form class="form"> 127 <div class="form-group"> 128 @Html.TextBox("SearchString", null, new { @class = "form-control Text", placeholder = "主機名" }) 129 <button type="submit" class="search"><span class="glyphicon glyphicon-search"></span></button> 130 </div> 131 </form> 132 </div> 133 <div class="col-sm-8" style="float:right">@Html.PagedListPager(Model, page => Url.Action("Index", new { page }))</div> 134 </div> 135 } 136 </div> 137 <div class="Date"> 138 @foreach (var item in Model) 139 { 140 <ul> 141 <li style="margin: 5px 0px 30px 0px">@item.SView.HostName</li> 142 <li>@item.SView.CPUType</li> 143 <li>@item.SView.CPUNum</li> 144 <li>@item.SView.RAMSize</li> 145 <li>@item.SView.RaidType</li> 146 <li>@item.SView.HDDNum</li> 147 <li style="margin: 30px 0px 5px 0px">@item.SView.CaseType</li> 148 </ul> 149 } 150 </div> 151 <div class="Date" style="margin:30px 0px 10px 20px;"> 152 @foreach (var item in Model) 153 { 154 <ul> 155 <li style="margin: 25px 0px 30px 0px">@item.SUView.CPUUsRate</li> 156 <li>@item.SUView.RAMUsRate</li> 157 <li>@item.SUView.HDDUsRate</li> 158 <li>@item.SUView.HDDIO</li> 159 <li>@item.SUView.HostcomputerLoad</li> 160 <li>@item.SUView.TheRootPartitionUsageRate</li> 161 <li style="margin: 30px 0px 5px 0px">@item.SUView.Time</li> 162 </ul> 163 } 164 </div> 165 <div class="Date" style="margin: 25px 0px 10px 20px;"> 166 @foreach (var item in Model) 167 { 168 <ul> 169 @foreach (var item1 in @item.NICView) 170 { 171 <li>@item1.NICType</li> 172 <li style="margin: 30px 0px 10px 0px">@item1.NICNum</li> 173 } 174 </ul> 175 } 176 </div> 177 <div class="Date" style="margin:15px 0px 10px 20px;"> 178 @foreach (var item in Model) 179 { 180 <ul> 181 @foreach (var item2 in @item.HDDView) 182 { 183 if (item2.RootHDD == 1) 184 { 185 <li>@item2.HDDType</li> 186 <li>@item2.HDDCap</li> 187 } 188 } 189 @foreach (var item2 in @item.HDDView) 190 { 191 if (item2.RootHDD != 1) 192 { 193 <li>@item2.HDDType</li> 194 <li>@item2.HDDCap</li> 195 } 196 } 197 </ul> 198 } 199 </div> 200 </div> 201 </body>
再將設計老王給的圖貼一下。
評價:豎版排版很好的解決了服務器屬性過多,須要顯示多條數據的問題,也解決了每一個服務器須要展現多個網卡數據和硬盤數據的問題。可是並無解決根本的問題,硬盤上限44,某個服務器可能搭載了44個硬盤,若是所有展現出來則頁面太長。
View層完成圖:
經理看後提了好多改進的方式,包括Model的命名不規範,數據庫中使用無心義的主鍵的原則,Model中主鍵外鍵的設置。Controller中Json數據能夠直接轉成model中的類型。以及View界面過長改進思路的問題。
此爲畢業後的第一個程序,把初版的代碼保留下來,接下來進行代碼的重構。