ASP.NET MVC深刻淺出系列(持續更新) ORM系列之Entity FrameWork詳解(持續更新) 第十六節:語法總結(3)(C#6.0和C#7.0新語法) 第三節:深度剖析各種數據結構(A

ASP.NET MVC深刻淺出系列(持續更新)

 

一. ASP.NET體系css

   從事.Net開發以來,最早接觸的Web開發框架是Asp.Net WebForm,該框架高度封裝,爲了隱藏Http的無狀態模式,ViewState功不可沒,經過的控件的拖拽和綁定,很快就能夠搭建出來一個Web項目,其開發速度遠勝Java、PHP,當年Web項目並不很重視體驗,沒有今天響應式,沒有各類前端js框架,因此在當年的WebForm,微軟是以引覺得豪的。html

  該框架畢竟有時代侷限性,隨着前端的崛起,隨着人們對項目體驗的提升,隨着項目的體量的增大,WebForm在當下強調鬆耦合、模塊化、組件化的時代,略顯落後,故微軟於2009年推出第一個開源框架,即MVC框架,俗稱ASP.Net MVC1,後面又陸續的推出 MVC二、三、四、5。如今最新的跨平臺Web開發框架 Core MVC,它隸屬於.Net Core框架,而非 .Net FrameWork下。前端

  下面用一張圖表示一下在Core出現以前,.Net在Web開發即ASP.NET中包含的內容。node

   簡單分析一下:WebPages(沒用過哎)、WebForms、MVC均爲ASP.NET下的Web開發框架,WebAPI負責構建HTTP常規服務,SignalR負責構建實時服務。web

   MVC和WebAPI簡單對比一下:MVC用來構建網站既關心頁面又關心數據,WebAPI只關心數據;MVC經過能夠經過Action的名字來接受CURD操做,而WebAPI經過HTTP的訪問方式(GET、PUT、POST、DELETE)來表達不一樣的CURD操做。ajax

  (WebService、WCF、WebAPI、SignalR在後面會有單獨的章節詳細介紹)數據庫

 

二. WebForm和MVC對比編程

1. WebFormwindows

   作過WebForm開發的朋友們應該很清楚,WebForm開發形式主要分爲三種:設計模式

  ①:服務器端控件,即拖拽控件(aspx)

  ②:通常處理程序(ashx) + html模板

  ③:html靜態頁 + ajax + 通常處理程序(ashx)

  請求模型:

  

  WebForm的幾個臭名昭著的缺點:封裝太強,致使開發不靈活;ViewState的無狀態;聲明週期模型複雜,對於初學者不易於理解。

2. MVC

  咱們常常從各類開發工程師(JAVA 、.NET、PHP)口中聽到MVC,但不一樣人說的MVC貌似相似,但又有區別,那麼MVC究竟是什麼呢?(相似的還有MVP和MVVM)

  1. 從宏觀上來講:MVC是框架分層的一種搭建思想,在最原始的項目中,沒有什麼框架分層之說,全部的項目代碼都在一個層裏,這樣會致使代碼冗雜,耦合性強,項目迭代升級困難,MVC是一種分層思想,將一個項目代碼分爲幾類,分別放到不一樣的層裏,Model層存儲一些數據和業務邏輯,View層處理頁面問題,Controller層用來接收人機交互指令。MVC分層思想和傳統的三層(數據庫訪問層、業務邏輯層、表現層)仍是有區別的。

  MVC的核心是分離了View和Model(即頁面和數據),Controller負責接收和發送指令,交給Model層處理。

  2. 從.Net的角度來講,MVC是微軟提供一個Web開發框架,全稱ASP.NET MVC,它是傳統三層中View層的一種功能細分,一種表現形式而已,與三層沒有直接關係。ASP.NET MVC框架中的開發流程圍繞:

  ① Model:存儲實體類,實現系統中的業務邏輯。

  ② View:頁面展現(Razor模板),展示給用戶。

  ③ Controller:頁面的邏輯處理,用來與用戶的交互,處理接受的Http請求。而後從Model中獲取相應的數據,轉發給View進行頁面展現。

 補充:經過Controller中的Action,能夠充當APP的服務端接口的做用,和WebAPI達到的效果一致,但訪問方式是有區別的。

  請求模型:

  下面列舉MVC框架的幾個典型的優勢:

  ①:鬆耦合,M-V-C分工明確,有利於代碼的維護。

  ②:便於Seo優化,能自定義url的生成規則。

  ③:ASP.NET MVC5是個出色的表現層框架。

  ④:對單元測試支持友好。

三. ASP.Net MVC 框架

1. 包含的技術

  ASP.NET MVC框架,這裏以MVC5爲例,涉及到的知識有:Model-View-Controller的使用、Area和Global的理解、路由配置、數據傳遞的方式、AOP思想的體現(4大過濾器),各類Result、Razor語法、HttpContext相關的五大對象、分佈視圖、特性的補充、Html擴展控件、Bundles壓縮js和css的原理、Owin約束、管道模型及MVC的工做原理。

   以及最新的Core MVC框架的相關知識。

2. 常見的約定

  ①:控制器命名一般以Controller結尾。

  ②:一個控制器對應一個View視圖文件夾,經常使用頁面都存放在裏面。

 

四. 系列章節

       第一節:走進MVC的世界(未完成)

       第二節:各類路由約束(動態路由、靜態路由、組合路由、正則約束、命名空間約束、區域內路由)

       第三節:Action向View傳值的四種方式(ViewData、ViewBag、TempData、Model)

       第四節:MVC中AOP思想的體現(四種過濾器)並結合項目案例說明過濾器的實際用法

       第五節:從源碼的角度理解MVC中各類Result(ActionResult、JsonResult、JavaScriptResult等)---待補充

       第六節:Razor引擎及相關語法(未完成)

       第七節:HtmlHelper及其擴展(未完成)

       第八節:layout和partialView、RenderPartial和Partial、 action和RenderAction(未完成)

       第九節:從源碼的角度分析MVC中的一些特性及其用法

       第十節:數據批註(DataAnnotationModel)和自定義驗證(包括Model級別的驗證)

       第十一節:Bundles壓縮合並js和css及原理分析

       第十二節:MVC中的一些特殊優化

       第十二節:管道模型(未完成)

       第十三節:HttpHander擴展及應用(自定義擴展名、圖片防盜鏈)

       第十四節:再探MVC中路由的奧祕

       第十五節:HttpContext五大核心對象的使用(Request、Response、Application、Server、Session)

       第十六節:利用MVC的擴展完成「一個後臺,多套前端頁面」的解決方案(未完成)

       第十七節:XXX

       第十八節:XXX

 

 

 

ORM系列之Entity FrameWork詳解(持續更新)

 

一. 談情懷

   從第一次接觸開發到如今(2018年),大約有六年時間了,最初階段鏈接數據庫,使用的是【SQL語句+ADO.NET】,那時候,什麼存儲過程、什麼事務 通通不理解,生硬的將SQL語句傳入SQLHelper類中,後來知道還要注意SQL注入,引入參數化的方式,如今回想一下,那個階段簡直Low到爆。

  (PS:如今不少場景下仍是須要使用ADO.NET,因此沒有最好,只有最適合)

       凡事都是從零開始的,正是這個階段積累,纔有了後續的發展。一次機會,接觸到了微軟的EF(ps:若是沒有記錯的話,當時用的是EF 5.0 的DBFirst模式),完全顛覆了個人開發觀念,不須要寫SQL語句(那時還不清楚EF也能夠調用SQL語句),Lambda表達式(並不知道Lambda還分Lambda表達式和Lambda語句),興奮了一陣,而後進入了漫長的EF摸索和填坑階段了(EF5.0→EF6.2→EF Core)。

    若是你以爲EF不靈活,不能調用存儲過程或自定義事務?若是你以爲EF在處理海量數據庫的時候會很慢?若是你以爲EF知足不了你的開發需求?。。。。。。 那麼也許該系列的文章會對你有些幫助。

二. ORM框架

  提及DotNet領域的ORM框架,咱們想到的有EF、NHibernate、FluentData、Dapper、SQLSugar等等。那麼到底什麼是ORM呢?

    ORM(Object Relational Mapping),中文名字:對象關係映射,它是面向對象思想的進一步的發揚光大,主要實現【程序對象】到【關係型數據庫】的映射。在以前使用ADO.NET開發的時候,數據庫訪問層(即 DAL),要寫不少增長、刪除、保存的方法,非常麻煩,若是引入ORM框架,它自帶CRUD的API(至關於DAL層已經給你寫好了),能夠自動生成SQL語句,因此做爲開發者而言,只須要關注對象便可。

   ORM的含義:

  ① O:Domain Object  領域模型

  ② R:Relational DataBase 關係型數據庫

  ③ M : Mapping 映射關係

      ORM的三大核心原則:

  ① 簡單性:以最簡單的模式建模數據。

  ② 傳達性:數據庫結構被任何人都能理解的語言文檔化。

       ③ 精確性:基於數據模型建立正確標準化的結構。

 

  EF的核心架構:

 

 

   ①  EDM(Entity Data Model):這是微軟提供的一個強大的可視化工具,用來生成 O、R、M的

  ②  兩種語法的查詢:LINQ to Entities 和 Entity SQL

  ③ ObjectServices:Linq to Entities 和Entity Client Data Provider 之間起到轉換做用

  ④ Entity Client Data Provider: 將Lambda轉換成SQL語句

  ⑤ ADO.Net Data Provider: 標準的ADO.Net

  ⑥ DataBase:數據庫

 

三. 從EF的入手,深刻理解ORM框架

   EF(Entity FrameWork),是微軟推出基於ADO.NET的數據庫訪問技術,它是一套ORM框架, 框架中包括了實例模型、數據模型、關係映射三部分,EF的上下文爲DbContext,EF在 【.Net FrameWork】版本中最新的是 6.2.0 版本,最穩定的是6.2版本,在【.Net Core】中推出 EF Core (即所謂的「EF7」,^_^,固然已經不這麼叫了)。

  EF包括三種模式:DBFirst、CodeFist、ModelFirst 。EF能夠調用SQL語句、可使用Linq查詢、可使用Lambda查詢,EF還有不少高級屬性,好比延遲加載、緩存屬性等等,在該系列文章中都將逐一詳細介紹。

  EF也有優缺點:

   優勢:①  EF是微軟自家的產品,和VS的集成度很高,極大的提升了開發效率。

        ②  EF中ModelFirst模式提供的模型設計器功能很強大,且採用T4模板生成的代碼的功能很強大。

                    ③  支持多數據庫開發,簡單的改變配置文件,就能夠切換數據庫。

          缺點: 在複雜的查詢生成SQL腳本的效率不是很高,浪費了性能。

     舉例:以前在開發中,一張幼兒表裏大約有60個字段左右,一個業務須要根據複雜的條件查詢出來一些信息(大約5個字段左右),當時因爲按開發人員的失誤,寫的Lambda表達式直接將全部字段查詢出來,致使該業務耗時很長大約25s左右,後來在個人引導下,先去數據庫中直接寫SQL語句,查詢全部字段,發現速度很快;而後將EF中的Lambda查詢改成只查詢指定的5個字段,發現速度由25s→3s左右,提高很是明顯,固然這也很好的說明了EF的侷限是在生成SQL的腳本效率上。

四. 系列章節

         第一節: 結合EF的本地緩存屬性來介紹【EF增刪改操做的幾種形式

         第二節: 比較EF的Lambda查詢和Linq查詢寫法的區別

         第三節: EF調用普通SQL語句的兩類封裝(ExecuteSqlCommand和SqlQuery )  

         第四節: EF調用存儲過程的通用寫法和DBFirst模式子類調用的特有寫法

         第五節: EF高級屬性(一) 之 本地緩存、當即加載、延遲加載(不含導航屬性)

         第六節: EF高級屬性(二) 之延遲加載、當即加載、顯式加載(含導航屬性)

         第七節: EF的三種事務的應用場景和各自注意的問題(SaveChanges、DBContextTransaction、TransactionScope)。

         第八節: EF的性能篇(一) 之 EF自有方法的性能測試   :

         第九節: EF的性能篇(二) 之 Z.EntityFramework.Extensions程序集解決EF的性能問題   :

         第十節: EF的三種追蹤實體屬性變化方式(DBEntityEntry、ChangeTracker、Local)     :

         第十一節: EF的三種模式(一) 之 DBFirst模式(SQLServer和MySQL兩套方案):

         第十二節: EF的三種模式(二) 之 ModelFirst模式(SQLServer爲例):

         第十三節: EF的三種模式(三) 之 來自數據庫的CodeFirst模式    :

         第十四節: EF的三種模式(四) 之 原生正宗的 CodeFirst模式的默認約定   :

         第十五節: EF的CodeFirst模式經過DataAnnotations修改默認協定   :

         第十六節: EF的CodeFirst模式經過Fluent API修改默認協定   :

         第十七節: EF的CodeFirst模式的四種初始化策略和經過Migration進行數據的遷移  :

         第十八節: EF的CodeFirst模式鏈接MySQL數據庫的解決方案(未完成)  :

         第十九節: 結合【表達式目錄樹】來封裝EF的BaseDal層的方法 :

         第二十節: 深刻理解併發機制以及解決方案(鎖機制、EF自有機制、隊列模式等):

         第二十一節:ADO層次上的海量數據處理方案(SqlBulkCopy類插入和更新):

         第二十二節: 以SQLServer爲例介紹數據庫自有的鎖機制(共享鎖、更新鎖、排它鎖等)(未完成)  :

         第二十三節: EF性能篇(三)之開源組件 Z.EntityFrameWork.Plus.EF6解決EF性能問題   :

         第二十四節:    :

         第二十五節:    :

 

 

 

第十六節:語法總結(3)(C#6.0和C#7.0新語法)

 

一. C# 6.0 新語法

1. 自動屬性初始化能夠賦值

複製代碼
 1     /// <summary>
 2     /// 自動屬性初始化
 3     /// </summary>
 4     public class UserInfor
 5     {
 6         public string userId { get; set; } = "123456";
 7 
 8         public string userName { get; set; } = "lmr";
 9 
10     }
11    {
12        Console.WriteLine("------------------------- 1. 自動屬性初始化能夠賦值----------------------------");
13        UserInfor uInfor = new UserInfor();
14        Console.WriteLine($"id={uInfor.userId},userName={uInfor.userName}");
15    }
複製代碼

2. 字符串嵌入值【$配合{}使用】

  特別注意:{}中若是有業務計算須要配合()使用

複製代碼
1    {
2                 Console.WriteLine("------------------------- 2. 字符串嵌入值【$配合{}使用】----------------------------");
3                 UserInfor uInfor2 = new UserInfor();
4                 Console.WriteLine($"名字爲:{uInfor2.userName}");
5                 //表明要輸入一個括號{}
6                 Console.WriteLine($"名字爲:{{{uInfor2.userName}}}");
7                 //{}中若是有業務計算須要配合()使用
8                 Console.WriteLine($"{(uInfor2.userName != "lmr" ? "小鮮肉" : "老鮮肉")}");
9    }
複製代碼

3. 能夠在命名空間出使用static聲明靜態類

 

1 {
2                 Console.WriteLine($"-------------------------3.能夠在命名空間出使用static聲明靜態類-------------------------");
3                 Console.WriteLine($"以前的使用方式: {Math.Pow(4, 2)}");
4                 Console.WriteLine($"導入後可直接使用方法: {Pow(4, 2)}");
5 }

4. 空值運算符(?)

  不須要判斷是否爲空了.

複製代碼
1  {
2                 Console.WriteLine($"-------------------------4. 空值運算符-------------------------");
3                 int? iValue = 10;
4                 Console.WriteLine(iValue?.ToString());//不須要判斷是否爲空
5                 string name = null;
6                 Console.WriteLine(name?.ToString());
7 }
複製代碼

5. 對象初始化

  能夠直接給字典類型經過相似「索引」的形式賦值 (原先是經過Add方法賦值)

複製代碼
 1  {
 2                 Console.WriteLine($"-------------------------5. 字典對象初始化-------------------------");
 3                 Dictionary<string, string> dicList = new Dictionary<string, string>()
 4                 {
 5                     ["1"] = "ypf1",
 6                     ["2"] = "ypf2",
 7                     ["3"] = "ypf3"
 8                 };
 9                 Dictionary<string, string> dicList2 = new Dictionary<string, string>()
10                  {
11                      { "1","lmr1"},
12                      { "2","lmr2"},
13                      { "3","lmr3"}
14                  };
15                 foreach (var item in dicList)
16                 {
17                     Console.WriteLine("key:{0},value:{1}", item.Key.ToString(), item.Value.ToString());
18                 }
19                 foreach (var item in dicList2)
20                 {
21                     Console.WriteLine("key:{0},value:{1}", item.Key.ToString(), item.Value.ToString());
22                 }
23             }
複製代碼

6. 異常過濾器增長when判斷條件

  只有符合when裏的條件,才能進入catch,若是不知足的話,直接代碼報錯,不能拋異常

複製代碼
 1   {
 2                 Console.WriteLine("-------------------------6. 異常過濾器增長when判斷條件-------------------------");
 3                 int epCheck = 100;
 4                 try
 5                 {
 6                     int.Parse("ypf");
 7                 }
 8                 catch (Exception e) when (epCheck > 11)
 9                 {
10                     Console.WriteLine(e.Message);
11                 }
12 }
複製代碼

7. nameof表達式

  把實例轉換成同名的字符串

1  {
2                 Console.WriteLine("-------------------------7. nameof表達式-------------------------");
3                 UserInfor userInfor = new UserInfor();
4                 Console.WriteLine(nameof(userInfor));
5 }

8. 在catch和finally語句塊裏使用await(暫不介紹,不經常使用)

9. 在屬性或方法上使用Lambada表達式

  ①:方法針對於只有一行的方法

  ②:屬性經過Lambda的形式進行賦值

複製代碼
   public class UserInfor
    {
        public string userId { get; set; } = "123456";

        public string userName { get; set; } = "lmr";

        /// <summary>
        /// Lambda類型的方法
        /// </summary>
        public void LambdaPrint() => Console.WriteLine("我是Lambda類型的方法");

        public string userSex => string.Format("男");
    }
 {
                Console.WriteLine("-------------------------9.在屬性或方法上使用Lambada表達式-------------------------");
                UserInfor userInfor = new UserInfor();
                userInfor.LambdaPrint();
                Console.WriteLine($"userSex的值爲:{userInfor.userSex}");
}
複製代碼

 

二. C# 7.0 新語法

1. out參數的改進

  在C#7.0以前, out參數使用前必須先聲明,而後傳入方法中,在C#7.0後能夠直接在傳入方法的時候進行聲明。

複製代碼
 1         /// <summary>
 2         /// out參數的改進
 3         /// </summary>
 4         /// <param name="x"></param>
 5         /// <param name="y"></param>
 6         public void DoNoting(out int x, out int y)
 7         {
 8             x = 1;
 9             y = 2;
10         }
11         {
12             Console.WriteLine("--------------------1-out參數的改進------------------------");
13             SevenEdition s = new SevenEdition();
14             s.DoNoting(out int x, out int y);
15             Console.WriteLine(x + y);
16          }
複製代碼

2. 元組(Tuples)

  ①:須要經過nuget安裝這個System.ValueTuple

  ②:元組建立的三種方式:語法糖、Create靜態方法、構造函數 (默認狀況下是經過Item一、Item2 。。。)

  ③:指定元祖命名:能夠經過左邊指定,也能夠經過右邊指定

  ④:將元祖應用於方法中返回值,即一個方法能夠返回多種不一樣類型的值,不須要封裝實體便可以實現。

複製代碼
 1         /// <summary>
 2         /// 默認元組命名
 3         /// </summary>
 4         /// <returns></returns>
 5         public (int, string, string) TupleWay1()
 6         {
 7             return (1, "ypf1", "ypf2");
 8         }
 9         /// <summary>
10         /// 指定元祖命名
11         /// </summary>
12         /// <returns></returns>
13         public (int m, string n, string k) TupleWay2()
14         {
15             return (1, "ypf1", "ypf2");
16         }
17            {
18                 Console.WriteLine("--------------------2-元組(Tuples)------------------------");
19                 //1. 建立元組的三種形式
20                 Console.WriteLine("--------------------1. 建立元組的三種形式------------------------");
21                 var tuple1 = (1, 2);   //語法糖
22                 var tuple2 = ValueTuple.Create("ypf", "lmr");  //Create靜態方法
23                 var tuple3 = new ValueTuple<int, string>(12, "ypf12");  //構造函數
24                 Console.WriteLine($"tuple1的兩個值爲:{tuple1.Item1}和{tuple1.Item2}");
25                 Console.WriteLine($"tuple1的兩個值爲:{tuple2.Item1}和{tuple2.Item2}");
26                 Console.WriteLine($"tuple1的兩個值爲:{tuple3.Item1}和{tuple3.Item2}");
27 
28                 //2. 指定元祖命名
29                 Console.WriteLine("--------------------2. 指定元祖命名------------------------");
30                 (int m, string n) tuple4 = (100, "erp");  //左邊命名
31                 Console.WriteLine($"tuple4的兩個值爲:{tuple4.m}和{tuple4.n}");
32                 var tuple5 = (one: 250, two: "spz");     //右邊命名
33                 Console.WriteLine($"tuple5的兩個值爲:{tuple5.one}和{tuple5.two}");
34 
35                 //3. 元祖應用於方法中返回值
36                 Console.WriteLine("--------------------3. 元祖應用於方法中返回值------------------------");
37                 SevenEdition s = new SevenEdition();
38                 //默認命名
39                 var result1 = s.TupleWay1();
40                 Console.WriteLine($"返回值有:{result1.Item1}、{result1.Item2}、{result1.Item3}");
41                 //指定命名
42                 var result2 = s.TupleWay2();
43                 Console.WriteLine($"返回值有:{result2.m}、{result2.n}、{result2.k}");
44 
45             }
複製代碼

3. 局部函數

  即在{}中聲明一個函數,只有{}中能使用

複製代碼
1   {
2                 Console.WriteLine("--------------------3-局部函數------------------------");
3                 DoSome();
4                 void DoSome()
5                 {
6                     Console.WriteLine("我是局部函數");
7                 }
8   }
複製代碼

4. 模式的比較和匹配

  ①:is的新模式。

    首先補充一個概念:拆箱和裝箱

    拆箱是將引用類型→值類型 (object ,class均爲引用類型)

    裝箱是將值類型→引用類型

  案例:有一個object類型的變量a,若是它是int類型,則+10賦值給m,並輸出m的值,下面看新老用法比較。

複製代碼
 1  {
 2                     Console.WriteLine("--------------------4-模式比較(is)------------------------");
 3                     object a = 9;
 4                     //老寫法
 5                     if (a is int)
 6                     {
 7                         int b = (int)a;  //拆箱
 8                         int c = b + 10;
 9                         Console.WriteLine($"老寫法c的值爲:{c}");
10                     }
11                     //新寫法
12                     if (a is int m)   //這裏的a直接拆箱爲m
13                     {
14                         int c = m + 10;
15                         Console.WriteLine($"新寫法c的值爲:{c}");
16                     }
17 }
複製代碼

  ②:switch-case中能夠自定義參數類型

  傳統狀況,全部的case中必須是同類型的;而在C# 7.0 新版本中,case中能夠不一樣類型,即Swich中能夠傳入任何類型,而後經過case中進行對應匹配,這就叫作模式匹配。

複製代碼
 1  /// <summary>
 2         /// 單一類型
 3         /// </summary>
 4         /// <param name="m"></param>
 5         /// <returns></returns>
 6         public dynamic SwitchWay1(string m)
 7         {
 8             dynamic data;
 9             switch (m)
10             {
11                 case "ypf1":
12                     data = m + "lmr1";
13                     break;
14                 case "ypf2":
15                     data = m + "lmr2";
16                     break;
17                 default:
18                     data = "spz00000";
19                     break;
20             }
21             return data;
22         }
23 
24         /// <summary>
25         /// 多種類型
26         /// </summary>
27         /// <param name="m"></param>
28         /// <returns></returns>
29         public dynamic SwitchWay2(object m)
30         {
31             dynamic data;
32             switch (m)
33             {
34                 case int a when a > 10:
35                     data = a + 10;
36                     break;
37                 case int b:
38                     data = b + 100;
39                     break;
40                 case String c:
41                     data = c + "mmmmmmmmmmmmmmm";
42                     break;
43                 default:
44                     data = "spz00000";
45                     break;
46             }
47             return data;
48         }
複製代碼
複製代碼
 1    {
 2                     Console.WriteLine("--------------------4-模式匹配(switch-case)------------------------");
 3                     SevenEdition sE = new SevenEdition();
 4                     //老用法
 5                     var data1 = sE.SwitchWay1("ypf1");
 6                     Console.WriteLine($"類型爲:{data1.GetType()},值爲:{data1}");
 7                     //新用法
 8                     var data2 = sE.SwitchWay2(1);
 9                     Console.WriteLine($"類型爲:{data2.GetType()},值爲:{data2}");
10 
11                     var data3 = sE.SwitchWay2(11);
12                     Console.WriteLine($"類型爲:{data3.GetType()},值爲:{data3}");
13 
14                     var data4 = sE.SwitchWay2("ypf1");
15                     Console.WriteLine($"類型爲:{data4.GetType()},值爲:{data4}");
16 
17  }
複製代碼

 

5. 數字文本語法的改寫

   好比10000000 能夠寫成10_000_000 ,方便識別。

複製代碼
 {
                Console.WriteLine("--------------------5-數字文本語法的改寫------------------------");
                long a = 10000000;
                long b = 10_000_000;
                Console.WriteLine($"a的值爲:{a},b的值爲:{b}");

 }
複製代碼

6. 補充一些特殊地方也能夠寫異常表達式 (不詳細測試了)

   好比:條件表達式(? :)、null合併運算符(??)、一些Lambda

  eg:private string _name = GetName() ?? throw new ArgumentNullException(nameof(GetName));

 

 

 

 

第三節:深度剖析各種數據結構(Array、List、Queue、Stack)及線程安全問題和yeild關鍵字

 

一. 各種數據結構比較及其線程安全問題

1. Array(數組):

  分配在連續內存中,不能隨意擴展,數組中數值類型必須是一致的。數組的聲明有兩種形式:直接定義長度,而後賦值;直接賦值。

  缺點:插入數據慢。

  優勢:性能高,數據再多性能也沒有影響

  特別注意:Array不是線程安全,在多線程中須要配合鎖機制來進行,若是不想使用鎖,能夠用ConcurrentStack這個線程安全的數組來替代Array。

複製代碼
 1  {
 2                 Console.WriteLine("---------------------------01 Array(數組)-----------------------------------");
 3                 //模式一:聲明數組並指定長度
 4                 int[] array = new int[3];
 5                 //數組的賦值經過下標來賦值
 6                 for (int i = 0; i < array.Length; i++)
 7                 {
 8                     array[i] = i + 10;
 9                 }
10                 //數組的修改經過下標來修改
11                 array[2] = 100;
12                 //輸出
13                 for (int j = 0; j < array.Length; j++)
14                 {
15                     Console.WriteLine(array[j]);
16                 }
17 
18                 //模式二:直接賦值
19                 string[] array2 = new string[] { "二胖", "二狗" };
20 }
複製代碼

2. ArrayList(可變長度的數組)

  沒必要在聲明的時候指定長度,即長度可變;能夠存放不一樣的類型的元素。

  致命缺點:不管什麼類型存到ArrayList中都變爲object類型,使用的時候又被還原成原先的類型,因此它是類型不安全的,當值類型存入的時候,會發生裝箱操做,變爲object引用類型,而使用的時候,又將object類型拆箱,變爲原先的值類型,這尼瑪,你能忍?

  結論:不推薦使用,建議使用List代替!!

  特別注意:ArrayList不是線程安全,在多線程中須要配合鎖機制來進行。

複製代碼
 1   {
 2                 Console.WriteLine("---------------------------02 ArrayList(可變長度的數組)-----------------------------------");
 3                 ArrayList arrayList = new ArrayList();
 4                 arrayList.Add("二胖");
 5                 arrayList.Add("馬茹");
 6                 arrayList.Add(100);
 7                 for (int i = 0; i < arrayList.Count; i++)
 8                 {
 9                     Console.WriteLine(arrayList[i] + "類型爲:" + arrayList[i].GetType());
10                 }
11 }
複製代碼

3. List<T> (泛型集合) 推薦使用

  內部採用array實現,但沒有拆箱和裝箱的風險,是類型安全的

  特別注意:List<T>不是線程安全,在多線程中須要配合鎖機制來進行,若是不想使用鎖,能夠用ConcurrentBag這個線程安全的數組來替代List<T>

複製代碼
 1 {
 2                 Console.WriteLine("---------------------------03 List<T> (泛型集合)-----------------------------------");
 3                 List<string> arrayList = new List<string>();
 4                 arrayList.Add("二胖");
 5                 arrayList.Add("馬茹");
 6                 arrayList.Add("大胖");
 7                 //修改操做
 8                 arrayList[2] = "葛帥";
 9                 //刪除操做
10                 //arrayList.RemoveAt(0);
11                 for (int i = 0; i < arrayList.Count; i++)
12                 {
13                     Console.WriteLine(arrayList[i]);
14                 }
15 }
複製代碼

4. LinkedList<T> 鏈表

  在內存空間中存儲的不必定是連續的,因此和數組最大的區別就是,沒法用下標訪問。

  優勢:增長刪除快,適用於常常增減節點的狀況。

  缺點:沒法用下標訪問,查詢慢,須要從頭挨個找。

  特別注意:LinkedList<T>不是線程安全,在多線程中須要配合鎖機制來進行。

複製代碼
{
                Console.WriteLine("---------------------------04 ListLink<T> 鏈表-----------------------------------");
                LinkedList<string> linkedList = new LinkedList<string>();
                linkedList.AddFirst("二胖");
                linkedList.AddLast("馬茹");

                var node1 = linkedList.Find("二胖");
                linkedList.AddAfter(node1, "三胖");
                //刪除操做
                linkedList.Remove(node1);
                //查詢操做
                foreach (var item in linkedList)
                {
                    Console.WriteLine(item);
                } 
}
複製代碼

5. Queue<T> 隊列

  先進先出,入隊(Enqueue)和出隊(Dequeue)兩個操做

  特別注意:Queue<T>不是線程安全,在多線程中須要配合鎖機制來進行,若是不想使用鎖,線程安全的隊列爲 ConcurrentQueue。

  實際應用場景:利用隊列解決高併發問題(詳見:http://www.cnblogs.com/yaopengfei/p/8322016.html)

複製代碼
 1  {
 2                 Console.WriteLine("---------------------------05 Queue<T> 隊列-----------------------------------");
 3                 Queue<int> quereList = new Queue<int>();
 4                 //入隊操做
 5                 for (int i = 0; i < 10; i++)
 6                 {
 7                     quereList.Enqueue(i + 100);
 8                 }
 9                 //出隊操做
10                 while (quereList.Count != 0)
11                 {
12                     Console.WriteLine(quereList.Dequeue());
13                 }
14 }
複製代碼

6. Stack<T> 棧

  後進先出,入棧(push)和出棧(pop)兩個操做

  特別注意:Stack<T>不是線程安全

複製代碼
 1  {
 2                 Console.WriteLine("---------------------------06 Stack<T> 棧-----------------------------------");
 3                 Stack<int> stackList = new Stack<int>();
 4                 //入棧操做
 5                 for (int i = 0; i < 10; i++)
 6                 {
 7                     stackList.Push(i + 100);
 8                 }
 9                 //出棧操做
10                 while (stackList.Count != 0)
11                 {
12                     Console.WriteLine(stackList.Pop());
13                 }
14 }
複製代碼

7. Hashtable

  典型的空間換時間,存儲數據不能太多,但增刪改查速度很是快。

  特別注意:Hashtable是線程安全的,不須要配合鎖使用。

複製代碼
{
                Console.WriteLine("---------------------------07 Hashtable-----------------------------------");
                Hashtable tableList = new Hashtable();
                //存儲
                tableList.Add("001", "馬茹");
                tableList["002"] = "二胖";
                //查詢
                foreach (DictionaryEntry item in tableList)
                {
                    Console.WriteLine("key:{0},value:{1}", item.Key.ToString(), item.Value.ToString());
                }
}
複製代碼

8. Dictionary<K,T>字典 (泛型的Hashtable)

  增刪改查速度很是快,能夠用來代替實體只有id和另外一個屬性的時候,大幅度提高效率。

  特別注意:Dictionary<K,T>不是線程安全,在多線程中須要配合鎖機制來進行,若是不想使用鎖,線程安全的字典爲 ConcurrentDictionary。

複製代碼
 1  {
 2                 Console.WriteLine("---------------------------08 Dictionary<K,T>字典-----------------------------------");
 3                 Dictionary<string, string> tableList = new Dictionary<string, string>();
 4                 //存儲
 5                 tableList.Add("001", "馬茹");
 6                 tableList.Add("002", "二胖");
 7                 tableList["002"] = "三胖";
 8                 //查詢
 9                 foreach (var item in tableList)
10                 {
11                     Console.WriteLine("key:{0},value:{1}", item.Key.ToString(), item.Value.ToString());
12                 }
13 }
複製代碼

強調: 

以上8種類型,除了Hashtable是線程安全,其他都不是,都須要配合lock鎖來進行,或者採用 ConcurrentXXX來替代。

詳細的請見:http://www.cnblogs.com/yaopengfei/p/8322016.html

 

二. 四大接口比較

1. IEnumerable

  是最基本的一個接口,用於迭代使用,裏面有GetEnumerator方法。

2. ICollection

  繼承了IEnumerable接口,主要用於集合,內部有Count屬性表示個數,像ArrayList、List、LinkedList均實現了該接口。

3. IList

  繼承了IEnumerable 和 ICollection,實現IList接口的數據接口可使用索引訪問,表示在內存上是連續分配的,好比Array、List。

4. IQueryable

  這裏主要和IEnumerable接口進行對比。

  Enumerable裏實現方法的參數是Func委託,Queryable裏實現的方法的參數是Expression表達式。

  實現IQueryable和IEnumabler均爲延遲加載,但兩者的實現方式不一樣,前者爲迭代器模式,參數爲Func委託,後者爲Expression表達式目錄樹實現。

 

三. yield關鍵字

1. yield必須出如今IEunmerable中

2. yield是迭代器的狀態機,能作到延遲查詢,使用的時候才查詢,能夠實現按序加載

3. 例子

  測試一:在 「var data1 = y.yieldWay();」加一個斷點,發現直接跳過,不能進入yieldWay方法中,而在「foreach (var item in data1)」加一個斷點,第一次遍歷的時候就進入了yieldWay方法中,說明了yield是延遲加載的,只有使用的時候才查詢。

  測試二:對yieldWay和commonWay獲取的數據進行遍歷,經過控制檯發現前者是一個一個輸出,然後者是先一次性獲取完,一下所有輸出來,證實了yield能夠作到按需加載,能夠在foreach中加一個限制,好比該數據不知足>100就不輸出。

複製代碼
 1     //*********************************  下面爲對比普通返回值和使用yeild返回值的方法  ************************************************
 2 
 3        /// <summary>
 4        /// 含yield返回值的方法
 5        /// </summary>
 6        /// <returns></returns>
 7         public IEnumerable<int> yieldWay()
 8         {
 9             for (int i = 0; i < 10; i++)
10             {
11                 yield return this.Get(i);
12             }
13         }
14         /// <summary>
15         /// 普通方法
16         /// </summary>
17         /// <returns></returns>
18         public IEnumerable<int> commonWay()
19         {
20             int[] intArray = new int[10];
21             for (int i = 0; i < 10; i++)
22             {
23                 intArray[i] = this.Get(i);
24             }
25             return intArray;
26         }
27 
28         /// <summary>
29         /// 一個獲取數據的方法
30         /// </summary>
31         /// <param name="num"></param>
32         /// <returns></returns>
33         private int Get(int num)
34         {
35             Thread.Sleep(1000);
36             return num * DateTime.Now.Second;
37         }
複製代碼
複製代碼
 1             Console.WriteLine("-----------------------下面是調用yield方法-----------------------");
 2             yieldDemo y = new yieldDemo();
 3             var data1 = y.yieldWay();
 4             foreach (var item in data1)
 5             {
 6                 Console.WriteLine(item);
 7             }
 8             Console.WriteLine("-----------------------下面是調用普通方法-----------------------");
 9             var data2 = y.commonWay();
10             foreach (var item in data2)
11             {
12                 Console.WriteLine(item);
13             }
複製代碼

 

 

 

各類通信鏈接方式

 

1. http  https (ajax)

2. 總結一下同一個項目下 先後交互的集中提交方式 (.Net特有的 EasyUI封裝的)

3. 跨域請求的幾種形式

3. HttpClient

4. WebService

5. WebAPI(重點)

6. socket

7. websocket (重點)+superSocket

8. SignalR (重點)

9. nodejs中的net通信模塊

10. WCF  (能夠棄療了)

 

 

 

設計模式篇

 

一. 什麼是設計模式

  糾結了很久,今天終於下定決心開始寫設計模式系列,由於這個系列章節確實很差寫,在這以前,也看了好多關於設計模式的博客、視頻、書籍等,大多數用的例子要麼貓啊狗啊、大雁等動物類;要麼就是學生類,教師類,吐槽一下,真shit,試想一下,哪一個項目中會用這些動物類教師類呢?

  我也和我同行的朋友交流了一下關於設計模式,對設計模式的理解,能夠分爲這麼幾個層次:

  ①:根本不知道什麼是設計模式。

  ②:據說過幾種設計模式,理解不深。

  ③:能寫出並理解幾種設計模式,但不知道在項目中該怎麼用。

  毋庸置疑,可否靈活的運用好設計模式,是一個名開發工程師邁向架構師的必經之路,上面說的這麼玄乎,那麼到底什麼是涉及模式呢?這裏先借助金庸的武俠小說來類比一下。

  做爲金庸迷的我,金庸老師的「飛雪連天射白鹿,笑書神俠倚碧鴛」14部小說每一部看了都不低於3遍以上,對裏面個各類武功也是瞭如指掌,像效果比較炫麗,威力比較大的有:「喬幫主降龍十八掌、段譽的六脈神劍、楊過的黯然銷魂掌、任我行的吸星大法等等」,這些都是外家功夫,種類不少,一我的可能會多種,這就比如.Net的中MVC、EF、SignalR等等;固然也有內功心法,典型的有:」少林和尚的易筋經、張無忌的九陽神功」,這兩種功夫自己並無太大的殺傷力,但會了這種功夫,更容易融會貫通外家功夫,使外家功夫發揮出更大效果,拿到咱們開發領域,「設計模式」就是內功心法,沒有語言之分,它是一種模式,一種思想指導着咱們開發。

  那麼怎麼才能算精通設計模式呢?

  看過《倚天屠龍記》的朋友可能會記得裏面有這麼一個場景:趙敏冒充明教挑戰張三丰的時候,張無忌辦成小道童出來救場,在對陣三個家奴的的時候,張三丰教了張無忌一套太極拳法,裏面有這麼一段對話:

 張三丰演示完後,問張無忌:「無忌,你記住了多少」,張無忌回答說:「無忌不才,只有一小部分沒有記住」;過了一會,張三丰又問道:「如今能記住多少」,無忌說:「太師傅,我已經所有忘記了」,這時,張三丰說:「無忌你能夠上了」,結果顯然而知,對手被打的那叫一個慘啊。

  因此:設計模式的最高境界是,忘記設計模式,將23種的設計模式天然而然的融入開發中,哈哈,固然這個有點難,沒有個五年以上的功力,很難達到這個層次。

  

二. 設計模式的內容

  設計模式是一種套路,是把 「別人成功的例子」 拿過來靈活運用,咱們的優秀的前輩總結出來7個設計原則23種設計模式

設計原則:

    1. 單一職責原則    2. 里氏替換原則    3. 依賴倒置原則

    4. 接口隔離原則    5. 迪米特原則(最小知道原則)    6. 開閉原則

    7. 組合聚合原則

 

設計模式:

  1. 建立型模式 :工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。

  2. 結構型模式:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

  3. 行爲型模式:策略模式、模板方法模式、觀察者模式、迭代器模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

 

   解釋:設計模式只是一個大概的套路,不能生搬硬套,有一些作法多是多個設計模式的融合,有的也很難歸爲某個設計模式。不要爲了設計模式而設計模式,沒有十全十美的代碼。

  在上述設計模式中,大部分設計模式都用到了上面的設計思想,在設計模式中,咱們會常常看到:開閉原則、里氏替換原則(多態)、面向接口編程、面向抽象編程、抽象類、override覆寫這幾種技術。

  若是對於抽象類或者override不明白的,有必要先看一下下面的章節:

                           第一節:從面向對象思想(oo)開發、接口、抽象類以及兩者比較 

                          第二節:重寫(new)、覆寫(overwrite)、和重載(overload)

 

三. 系列章節

   下面將由淺入深,結合實際案例來說解設計原則和設計模式。

 

     第一節:見識設計模式的神器之處。

     第二節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第三節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第四節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第五節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第六節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第七節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第八節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第九節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十一節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十二節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十三節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十四節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十五節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十六節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十七節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十八節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第十九節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十一節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十二節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十三節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十四節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十五節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十六節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十七節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十八節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第二十九節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第三十節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第三十一節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第三十二節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     第三十三節:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 

 (進度:一週寫 2-3篇,大約2個半月 完成該系列)

 

 

第十二節: 總結Quartz.Net幾種部署模式(IIS、Exe、服務部署【藉助TopSelf、服務類】)

 

一. IIS部署

  好比在MVC框架中集成了Quartz.Net定時調度,此時該調度系統會隨着MVC框架被掛在IIS下,IIS會進程回收,因此大部分開發都會遇到Quartz掛在IIS下一段時間很差用。

  補充:IIS能夠設置定時自動回收,默認回收是1740分鐘,也就是29小時。IIS自動回收至關於服務器IIS重啓,應用程序池內存清空,全部數據被清除,至關於IIS重啓,在度量快速開發平臺服務器端,爲了減少數據庫負擔,內存中暫存了不少信息,不適合頻繁的回收,由於回收會形成服務器端全部存在內存中的數據丟失,若是沒有及時保存到數據庫中,可能致使程序出現問題。而若是系統使用高峯時期,並不適合回收,回收可能致使幾十秒IIS無響應,對於正在工做的人員來講,是一種很很差的體驗,會覺得是網絡或者掉線等問題。

  解決方案:關閉該項目在IIS上對應的進程池的回收機制。

  如何關閉進程池的回收機制:選中IIS中部署的項目對應的進程池,點擊【高級設置】,裏面有5個核心參數:

    ① 發生配置更改時禁止回收:若是爲True,應用程序池在發生配置更改時將不會回收。

    ② 固定時間間隔(分鐘):超過設置的時間後,應用程序池回收,設置爲:0 意味着應用程序池不回收。系統默認設置的時間是1740(29小時)。

    ③ 禁用重疊回收:若是爲true,將發生應用程序池回收,以便在建立另外一個工做進程以前退出現有工做進程

    ④ 請求限制:應用程序池在回收以前能夠處理的最大請求數。若是值爲0,則表示應用程序池能夠處理的請求數沒有限制。

    ⑤ 生成回收事件日誌條目:每發生一次指定的回收事件時便產生一個事件日誌條目。

    總結:即便能夠將IIS進程池回收關掉,仍然不建議把Quartz掛到IIS下,長時間不回收,會存在內存溢出的問題。

 

二. C/S程序直接運行

  咱們能夠用控制檯的形式或者Winform的形式單獨作一套定時調度系統,與主框架分類,也便於維護,能夠直接將exe程序或者Winform窗體程序在服務器上運行。

  總結:該方法不存在回收的問題,但直接在服務器上運行,容易不當心被運維人員關掉了。

  對於專業一點的人員來講,該方案,直接運行程序太Low了,因此一般是將exe程序發不成windows服務,經過服務的開啓和關閉來 維護。

 

三. 藉助topshelf來進行的windows服務部署 

  官網:http://topshelf-project.com/ , 這是一種通用的發佈服務的方式,步驟以下:

  1. 經過NuGet下載 Topshelf 的程序集

  2. 配置QuartzService類,充當定時任務的服務端程序

    ①:構造函數中執行定時調度任務

    ②:Start()方法控制調度的開啓 (必填)

    ③:Stop()方法控制調度的關閉 (必填)

    ④:Pause()方法暫停調度 (選填)

    ⑤:Continue()方法繼續調度 (選填)

    ⑥:Shutdown() 關閉 (須要支持)

  3. 在主程序中經過topshelf代碼調用: HostFactory.Run 詳見主程序。(在裏面能夠設置服務的名稱、描述等

  4. 經過指令進行服務發佈和卸載(查看windows服務:services.msc)

   ①:經過cmd命令定位到bin文件目錄下(以管理員身份運行)

    (eg: 先輸入 d: 切換到D盤,再執行下面的命令  cd D:\06-個人開發之路\DotNet體系\04-DotNet專題篇\01-Quartz.Net定時調度\01-Code\MyQuarzt\QuartzDemo\bin\Debug  )

   ②:QuartzDemo.exe help: 查看指令

     QuartzDemo.exe install: 安裝服務

     QuartzDemo.exe install start : 安裝服務且開啓

     QuartzDemo.exe uninstall :卸載服務

  截止此處,大功告成,能夠看到D盤中多了一個txt文件,每隔3s多一條數據

 下面分享整個過程的代碼部署的相應截圖:

 (1). Quartz代碼和TopSelf調用代碼:

複製代碼
 1    public class QuartzService
 2     {
 3         IScheduler scheduler = null;
 4         /// <summary>
 5         /// 定時調度業務
 6         /// </summary>
 7         public QuartzService()
 8         {
 9             //1.建立做業調度池(Scheduler)
10             scheduler = StdSchedulerFactory.GetDefaultScheduler();
11 
12             //2.建立一個具體的做業即job (具體的job須要單獨在一個文件中執行)
13             var job = JobBuilder.Create<HelloJob5>().Build();
14 
15             //3.建立並配置一個觸發器即trigger   3s執行一次
16             var trigger = TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(3)
17                                                                            .RepeatForever()).Build();
18             //4.將job和trigger加入到做業調度池中
19             scheduler.ScheduleJob(job, trigger);
20         }
21         /// <summary>
22         /// 開啓任務
23         /// </summary>
24         public void Start()
25         {
26             scheduler.Start();
27         }
28         /// <summary>
29         /// 關閉任務
30         /// </summary>
31         public void Stop()
32         {
33             //true:表示該Sheduler關閉以前須要等如今全部正在運行的工做完成才能關閉
34             //false:表示直接關閉
35             scheduler.Shutdown(true);
36         }
37         /// <summary>
38         /// 暫停調度
39         /// </summary>
40         public void Pause()
41         {
42             scheduler.PauseAll();
43         }
44         /// <summary>
45         /// 繼續調度
46         /// </summary>
47         public void Continue()
48         {
49             scheduler.ResumeAll();
50         }
51 
52     }
複製代碼
複製代碼
 1             HostFactory.Run(x =>                                 //1
 2                     {
 3                         x.Service<QuartzService>(s =>                        //2
 4                         {
 5                             s.ConstructUsing(name => new QuartzService());     //3
 6                             //開啓和關閉  必選項
 7                             s.WhenStarted(tc => tc.Start());              //4
 8                             s.WhenStopped(tc => tc.Stop());               //5
 9 
10                             // optional pause/continue methods if used  
11                             // 暫停和繼續  選填
12                             s.WhenPaused(tc => tc.Pause());
13                             s.WhenContinued(tc => tc.Continue());
14 
15                             //// optional, when shutdown is supported
16                             //s.WhenShutdown(tc => tc.Shutdown());
17 
18                         });
19                         x.RunAsLocalSystem();                            //6
20                         x.SetDescription("測試藉助TopSelf將Quartz發佈成服務");        //7
21                         x.SetDisplayName("QuartzService");                       //8
22                         x.SetServiceName("QuartzService2");                       //9
23                     });
複製代碼

(2). 定位到指定路徑,並進行相應的服務部署

a. 不少指令

b. 安裝服務並開啓

 

查看服務列表:

 

查看服務運行結果:

 

刪除服務:

 

 

三. 藉助window服務類

   這裏不詳細介紹(網上一堆一堆的),推薦採用上面的TopShelf的服務發佈方式。

相關文章
相關標籤/搜索