第七節:語法總結(1)(自動屬性、out參數、對象初始化器、var和dynamic等) 圖片放大鏡 JavaScript-基礎 用javascript寫原生ajax(筆記) 初遇 Asp.net MV

第七節:語法總結(1)(自動屬性、out參數、對象初始化器、var和dynamic等)

 

一. 語法糖簡介javascript

      語法糖也譯爲糖衣語法,是由英國計算機科學家彼得·約翰·蘭達(Peter J. Landin)發明的一個術語,指計算機語言中添加的某種語法,這種語法對語言的功能並無影響,可是更方便程序員使用。一般來講使用語法糖可以增長程序的可讀性,從而減小程序代碼出錯的機會。css

      須要聲明的是「語法糖」這個詞絕非貶義詞,它能夠給我帶來方便,是一種便捷的寫法,編譯器會幫咱們作轉換;並且能夠提升開發編碼的效率,在性能上也不會帶來損失。html

      在編譯器發展早期,編譯器科學家門一直在千方百計的優化編譯器生成的代碼,這個時候,編譯器作的主要是對機器優化,由於那個時候機器的時間很是寶貴,機器運算速度也不快,今天咱們有了足夠好的機器了(但並非說咱們能夠不關注性能的編寫程序),並且做爲編寫軟件的人來講,比機器的時間寶貴得多,因此今天的編譯器也在向人優化了,從編程語言的發展之路來說,今天的編程語言比昨天的語言更高級,也更人性化了,咱們只要編寫更少的代碼,更符合人的思惟的代碼,而只要關注咱們值的關注的地方。體力活兒就交給編譯器吧。前端

二. 經常使用語法糖java

1. 自動屬性jquery

(1).  傳統的方式在類中聲明一個屬性,須要先聲明一個私有變量的字段,而後在配合公有屬性,以下面的:userId屬性。程序員

(2). 利用自動屬性:不須要字段,聲明一個空屬性,直接get,set(快捷鍵:prop),編譯時編譯器爲咱們生成存取數據的字段. 以下面的:userName屬性。web

複製代碼
 1  public class userInfor
 2     {
 3         //私有字段
 4         private string _userId;
 5         //公有屬性
 6         public string userId
 7         {
 8             get
 9             {
10                 return _userId;
11             }
12             set
13             {
14                 _userId = value;
15             }
16         }
17 
18         public string useName { get; set; }
19 
20 
21         /// <summary>
22         /// 爲了後面的反射調用
23         /// </summary>
24         public void Test()
25         {
26             Console.WriteLine("我是一個方法");
27         }
28 
29     }
複製代碼

2. var和dynamicajax

(1). var類型:聲明變量的時候能夠不指定類型,由編譯器編譯的時候來指定類型。sql

  ①:必須在定義的時候初始化

  ②:必須是局部變量

  ③:一旦初始化完成,不能再給變量賦與初始值不一樣類型的值了,可是能夠賦相同類型的不一樣值.

  ④:var在效率是和使用強類型方式定義變量是同樣的

(2). dynamic類型:編譯期間不作任何檢查,運行期間才肯定類型。

  ①:定義的時候能夠沒必要初始化

  ②:能夠是全局變量,也能夠是局部變量

   dynamic在反射中的應用:經過反射拿到類後,賦值給dynamic類型,該類型的對象能夠直接點來調用方法

   缺點:dynamic在運行的時候才進行檢測,致使編譯的時候即便有錯誤也不會被發現; 不能用dynamic類型給肯定類型的變量進行賦值

複製代碼
 1  public class CompareTwo
 2     {
 3         //2. 可以使用的範圍
 4         // var b1 = 1;        //報錯,var必須定義在方法呃逆
 5         // dynamic b2 = 2;    //正常
 6         public static void Show()
 7         {
 8             {
 9                 //1. 初始化比較
10                 //var a1;         //報錯,定義的時候必須初始化
11                 //dynamic a2;     //正常
12             }
13             {
14                 //3. 賦值問題
15                 var c1 = 2;
16                 //c1 = "2";   //報錯,初始化完成不能賦值不一樣類型的變量
17                 c1 = 3;    //正常,初始化完成能夠賦值相同類型的變量的不一樣值
18 
19                 dynamic d1 = 2;
20                 d1 = "2";      //正常,運行時檢查進行類型指定,因此在編譯的時候不會報錯
21                 d1 = 3;       //正常
22 
23 
24                 var userInfor = new userInfor();
25                 userInfor.useName = "1";
26                 userInfor.userId = "2";
27                 // userInfor.fk123();    //報錯,編譯不經過
28 
29                 dynamic userInfor2 = new userInfor();
30                 userInfor2.userId = "1";
31                 userInfor2.useName = "ypf";
32                 //調用不存在的方法  (由於編譯的時候根本不檢查,因此不會報錯,運行的時候報錯)
33                 //userInfor2.fk123();    //編譯期間不報錯,運行的時候報錯
34 
35             }
36             {
37                 //4. dynamic在反射中的應用
38                 //4.1 常規反射調用方法
39                 Type type1 = typeof(userInfor);
40                 object oStudent = Activator.CreateInstance(type1);
41                 MethodInfo method = type1.GetMethod("Test");
42                 method.Invoke(oStudent,null);
43 
44                 //4.2 利用dynamic簡化調用
45                 //定義和編譯的時候能夠是任何類型,運行的時候進行轉換
46                 dynamic oStudent2 = Activator.CreateInstance(type1);
47                 oStudent2.Test();
48 
49             }
50         }
51     }
複製代碼

3. 可選參數

給方法的參數能夠指定默認值,若是在調用該方法的時候,不傳入該參數,則走默認值,傳入的話,則覆蓋默認參數.

(1).  有默認值的參數必須定義在沒有默認值的參數以後

(2).  默認參數必須是常量,不能是變量

(3).  ref和out參數不能指定默認值

複製代碼
1   public class OptionalParas
2     {
3         public static void Test(string useName,string userPwd,int userAge=16,string userSex="男")
4         {
5             Console.WriteLine("userName:{0},userPwd:{1},userAge:{2},userSex:{3}", useName, userPwd, userAge, userSex);
6         }
7     }
複製代碼
1        //3.可選參數
2             Console.WriteLine("----------------------3.可選參數-------------------------");
3             OptionalParas.Test("ypf1", "123456");
4             OptionalParas.Test("ypf2", "654321", 56, "女");

4. 對象(集合)初始化器

複製代碼
 1  public class ObjectInitilize
 2     {
 3         public static void Test()
 4         {
 5            
 6                 //一.對象初始化
 7                 //1. 傳統初始化對象的方式
 8                 userInfor uInfor1 = new userInfor();
 9                 uInfor1.userId = "1";
10                 uInfor1.useName = "ypf1";
11 
12                 //2.對象初始化器
13                 userInfor uInfor2 = new userInfor()
14                 {
15                     userId="2",
16                     useName="ypf2"
17                 };
18                 userInfor uInfor3 = new userInfor()
19                 {
20                     userId = "3",
21                     useName = "ypf3"
22                 };
23             
24                 //二. 集合初始化
25                 //1. 傳統方式
26                 List<userInfor> uList = new List<userInfor>();
27                 uList.Add(uInfor1);
28                 uList.Add(uInfor2);
29 
30                 //2. 集合初始化器
31                 List<userInfor> uList2 = new List<userInfor>(){
32                     uInfor1,
33                     uInfor2,
34                     new userInfor(){
35                         userId="4",
36                         useName="ypf4"
37                     }
38                 };
39                 
40         }
41     }
複製代碼

5. ref和out

兩者共同的使用場景,將ref或out參數傳入方法中,執行完方法後,能夠直接使用ref或out參數值。

  (1). ref必須在使用前賦值,即傳入方法前進行定義並賦值

  (2). out必須在方法中賦值而後使用,在調用方法前聲明兩個未實例化的變量,用來傳入和接收使用

舉例:有兩個int類型的值num1和num2,分別使用ref和out傳入對應的方法中,進行值交換。

複製代碼
 1  public class CompareRO
 2     {
 3         /// <summary>
 4         /// ref的使用
 5         /// </summary>
 6         public static void TestRef()
 7         {
 8             int num1 = 5;
 9             int num2 = 10;
10             Func1(ref num1, ref num2);
11             Console.WriteLine("num1的值爲:{0},num2的值爲:{1}", num1, num2);
12         }
13 
14         public static void TestOut()
15         {
16             int num1;
17             int num2;
18             Func2(out num1, out num2);
19             Console.WriteLine("num1的值爲:{0},num2的值爲:{1}", num1, num2);
20         }
21 
22         #region ref版參數值交換
23         public static void Func1(ref int n1, ref int n2)
24         {
25             int a = n1;
26             n1 = n2;
27             n2 = a;
28         }
29         #endregion
30 
31         #region out版參數值交換
32         public static void Func2(out int n1,out int n2)
33         {
34             n1 = 5;
35             n2 = 10;
36             int a = n1;
37             n1 = n2;
38             n2 = a;
39         }
40         #endregion
41 
42     }
複製代碼

6. 匿名類/匿名方法

 

   詳見:.Net進階系列(3)-匿名類、匿名方法、擴展方法

 

7. 擴展方法

 

   詳見:.Net進階系列(3)-匿名類、匿名方法、擴展方法

 

圖片放大鏡

 

css:jquery.jqzoom.css

插件:jquery.jqzoom-core.js

<a class="big" href="image/big.jpg">
    <img src="image/small.jpg"/>
</a>
//編寫腳本
$(".big").jqzoom();

配置參數:

zooType,默認值:‘standard’,另外一個值是‘reverse’,是否將原圖用半透明圖層遮蓋

zoomWidth,默認值:2000,放大窗口的寬度

zoomHeight,默認值:200,放大窗口的高度

xOffset,默認值:10,放大窗口相對於原圖的X軸偏移值,能夠爲負

yOffset,默認值:0,放大窗口相對於原圖的y軸偏移值,能夠爲負

position,默認值:‘right’,放大窗口的位置,值還能夠是‘right’、‘left’,‘top’,‘bottom’

lens,默認值:true,若爲false,則不在原圖上顯示鏡頭

imageOpacity,默認值:0.2,當zoomType的值爲‘reverse’時,這個參數用於指定遮罩層的透明度

title,默認值:true,在放大窗口中顯示標題,值能夠爲a標記的title值,若無,則爲原圖的title值

showEffect,默認值:‘show’,顯示放大窗口時的效果,值能夠爲:‘show’,‘fadein’

hideEffect,默認值:‘hide’,隱藏放大窗口時的效果,值能夠爲:‘hide’,‘fadeout’

fadeinSpeed,默認值:‘fast’,放大窗口的漸顯速度(‘fast’,‘slow’,‘medium’)

fadeoutSpeed,默認值:‘slow’,放大窗口的漸隱速度(‘fast’,‘slow’,‘medium’)

showPreload,默認值:true,是否顯示加載提示Loading zoom(‘true’,‘false’)

preloadText,默認值:‘Loading zoom’,自定義加載提示文本

preloadPosition,默認值:‘center’,加載提示的位置,值也能夠爲‘bycss’,以經過css指定位置

 

JavaScript-基礎

 

Date 

 date.toString()  獲取世界時間,會提示當前時區

var data = new Date();
alert(date.toString());

  date.toLocaleString()  獲取當前時區的當前時間

超連接不跳轉

1、讓js函數返回false,在click也返回false

function hi(){
  alert("你好")  ;
  return false;  
}
<a href="http://www.baidu.com" onclick="return hi();">打招呼</a>

2、將href指定成一段腳本

<a href="javascript:hi();">打招呼</a>

數據類型

boolean      布爾

number    數字

string     字符串

Undefined     未定義

Null           空對象

Object       對象類型

Undefined類型、Null類型都是隻有一個值的數據類型,值分別爲undefined與null

null是一個object的值

查看變量的類型typeof  變量名或typeof(變量名),返回變量類型的字符串

//返回的是function
alert(typeof(date))
//返回的是string
alert(typeof(date()))//調用方法返回字符串

類型轉換:類型名(變量名)或parse***(變量名)

//當變量被聲明後,沒有初始化,值爲undefined

判等

雙等號==判斷值是否相等

三等號===先判斷類型是否相同,再判斷值是否相等

undefined==null  true

undefined===null  false

123==「123」    true

123===「123」    false

如何判斷變量是否可用?

  先判斷類型是否爲undefined,再判斷值是否爲null,不然可用

isNan()  非數字判斷

alert(isNaN('123'))    //false 能轉成數字的都是false
alert(isNaN('abc'))

eval()  將一段字符串當作js代碼執行

應用場景:當從文本框中獲取值時,獲得的是字符串,但願那段字符串當作js執行,則使用eval()

eval('alert("abc")')

方法

  使用關鍵字arguments獲取因此的參數,是一個數組

複製代碼
//可變參數
function sum(){
  var res=0;
  for(var i=0;i<arguments.length;i++)    {
      res+=argument[i];
  }
}
sum(1,2,3,4,5);
複製代碼

  js不支持方法重載,若是方法重名,後寫的函數會把以前的覆蓋掉

匿名函數

1、能夠將方法賦值給一個變量,這個變量表示一個方法

var fn = function(a,b){alert(a+b);};
//調用
fn(1,2);

2、定義時完成調用

(function(){})()

3、賦值給一個變量完成調用

new Function("a","b","return a+b");

閉包(主要做用是類的定義)

  支持在函數內部調用函數以前聲明過的變量

  做用域鏈:變量的做用域在當前函數中,及當前函數內部定義的函數中,造成了一個鏈條(缺點:會讓變量的值在內存中長期存放,沒法釋放,儘可能避免閉包的發生)

複製代碼
//定義一個函數say
            function say(name){
                //返回一個函數
                return function(){
                    //輸出name的值
                    alert("我是"+name)
                }
            }
            //調用say函數,將返回值賦值給fn
            var fn = say("小明");
            //調用fn
            fn();
複製代碼

複製代碼
window.onload=function(){
                var btn = document.getElementsByName("happy");
                for(var i=0;i<btn.length;i++){
                    //逐個爲按鈕註冊點擊事件
                    btn[i].onclick=function(){
                        //正確寫法
                        //this.value="noHappy";
                        //錯誤緣由,i的閉包,當調用此方法時,因爲該方法沒有i,因此去外層方法尋找,但因爲當時已經循環完,因此i爲7,也就是說,無論點擊哪一個按鈕,執行的都是第8個(也就是i爲7)按鈕的事件
                        document.getElementById(i).value="noHappy";
                    }
                }
            }

<input type="button" name="happy" id="0" value="happy"/>
<input type="button" name="happy" id="1" value="happy"/>
<input type="button" name="happy" id="2" value="happy"/>
<input type="button" name="happy" id="3" value="happy"/>
<input type="button" name="happy" id="4" value="happy"/>
<input type="button" name="happy" id="5" value="happy"/>
<input type="button" name="happy" id="6" value="happy"/>
<input type="button" name="happy" id="7" value="happy"/>

複製代碼

模擬面向對象

複製代碼
//第一種方式
            //爲類增長成員
            function Person(gender){
                //在類內部聲明一個Gender屬性,初始化爲gender值
                this.Gender=gender;
                this.say=function(){
                    alert("我是"+this.Gender+"的");
                }
            }
            //使用構造方法建立對象
            var women=new Person("女");
            //調用方法
            person.say();
            alert(typeof(women));//object
            alert(typeof(Person("女")));//undefined,由於Person做爲函數時,沒有返回值,因此是undefined
            alert(typeof(Person));//function,Person就是一個函數,類型是function
//第二種方式
            //爲對象增長屬性
            function Person(){}
            var p=new Person();
            p.Name="小明";//爲對象p新增了一個Name屬性
            p.say=function(){
                alert(p.Name);
            }
            p.say();
            //新建的對象,是沒有Name屬性的,由於類Person中沒有Name屬性
            var p1=new Person();
            alert(p1.Name)
複製代碼

原型

複製代碼
//原型:對象的類型
            function Person(){
                this.Age=18;
            }
            var p = new Person();
            //訪問原型,爲原型註冊數據成員,下面兩種結果同樣
            p.__proto__.Name="小紅";//兩個下劃線
            Person.prototype.Name="小紫";
複製代碼

集合

複製代碼
//使用[]定義數組
            var arr=[1,'a',"小明"];
            arr[0]
            //鍵值對{鍵:值}
            var arr2={name:"小明",age:18,gender:'男'};
            arr2["name"]//將arr2認爲是集合,銅鼓鍵訪問值
            arr2.name//將arr2任務是json,經過屬性訪問值
//定義json數組
            var temp=[{
                name:"小明",
                age:17
            },{
                name:"小紅",
                age:18
            },{
                name:"小紫",
                age:18
            }];
//輸出對象的name
            for(var item in temp){
                alert(temp[item].name)//temp[item]["name"]與前面結果相同
            }
複製代碼

 

 
 

用javascript寫原生ajax(筆記)

 

 

  AJAX  的全名叫作  Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。它最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容,優化用戶體驗。平時本身使用 ajax 作請求都是用的 jquery 裏封裝好的 ajax 函數,下面用javascript來寫一寫原生的ajax請求。

  插播一條ajax的知識點:

   

 

       ajax請求頭中特有的字段:X-Requested-With: XMLHttpRequest; 你能夠在服務端經過這個字段來判斷一個http請求是否爲ajax請求。

大體分爲如下四個步驟:

一、建立ajax對象 (考慮各個瀏覽器的兼容性)

二、鏈接到服務器

三、發送請求

四、接收返回值進行處理

 

複製代碼
<script>
window.onload=function()
{
    //由一個按鈕來觸發發送ajax請求的動做
    var btn = document.getElementById("btn");
    btn .onclick = function()
    {
        //1.建立ajax對象,考慮瀏覽器的兼容性

        var xhr;    //ajax對象

        if(window.XMLHttpRequest)
        //若是有XMLHttpRequest,那就是非IE6版本如下的瀏覽器。
        {
            //建立ajax對象
            var xhr= new XMLHttpRequest();
        }
        else
        //若是沒有XMLHttpRequest,那就是IE6版本一下的瀏覽器
        {
            //IE6瀏覽器建立ajax對象
            var xhr= new ActiveXObject("Microsoft.XMLHTTP");
        }

        //2.鏈接服務器
        //open(方法、文件名、是否異步傳輸)
        //方法:
            //傳輸方式是get方式仍是post方式。
        //文件名
            //告訴服務器要讀哪一個文件
        //異步傳輸
            //基本上都是用異步

        /*請求爲GET方式*/
        /*GET請求方式會首先找瀏覽器中的緩存,加上t='+new Date().getTime()"的目的是爲了消除緩存,每次的t的值不同。*/
        xhr.open("GET","/quest?t='+new Date().getTime()",true);

        //3.發送請求
        /*POST請求時能夠帶參數,做爲請求的參數*/
        xhr.send();

        //4.接收返回
        //客戶端和服務器端有交互的時候會調用onreadystatechange
        xhr.onreadystatechange=function()
        {
            //xhr.readyState  //瀏覽器和服務器,進行到哪一步了。
                //0->(未初始化):尚未調用 open() 方法。
                //1->(載入):已調用 send() 方法,正在發送請求。
                //2->(載入完成):send() 方法完成,已收到所有響應內容。
                //3->(解析):正在解析響應內容。
                //4->(完成):響應內容解析完成,能夠在客戶端調用。
            if(xhr.readyState==4)
            {
                if(xhr.status==200)//判斷是否成功,若是是200,就表明成功
                {
                    alert("成功"+xhr.responseText); /*xhr.responseText 是服務器返回的文本信息*/
                }
                else
                {
                    alert("失敗");
                }
            }
        };
    }
};

</script>                  
複製代碼

 

以上就是簡單的使用javascript寫原生ajax請求的代碼。

 

最後補充:ajax是不能進行跨域請求的,這也是侷限性所在,若是想要進行跨域請求,可使用jsonp來實現,它利用的是請求js文件時能夠進行跨域請求的原理。

 

 

初遇 Asp.net MVC 數據庫依賴緩存那些事兒

 

聲明:本文爲做者原創文章,轉載請註明出處 http://www.javashuo.com/article/p-abxcnagj-de.html 

問題背景:

  最近作一個很是簡單的功能,就是使用ajax請求的方式從服務端請求一段下拉表的數據。

  之前也有作過這個功能,只不過此次作這個功能的時候冒出了一個想法:

  我請求的這段數據它是一段相對比較固定的數據,也就是說它不怎麼改變,也許幾個月纔會改變一次。因爲這種數據的變化週期很長,因此之前作這種功能的時候,會使用緩存進行優化,能夠直接從緩存中讀取數據,避免每一次接收了ajax請求後都要向數據庫要數據,減小服務器與數據庫之間的交互,減輕數據庫服務器的壓力。可是問題來了,數據的變化週期再長終究是要變化的,當數據庫中的數據變化的時候你就要對舊有的緩存內容進行移除(remove)操做,好的,之前我是這樣作的:

複製代碼
        public ActionResult GetAllFJs()
        {
            //嘗試從緩存中取出數據
            var FJIdNames = HttpContext.Cache["FJIdNames"];

            if (null == FJIdNames)   //緩存中沒有數據
            {
                //從數據庫中查詢出數據
                FJIdNames = FJService.GetAll().Select(fj => new { Id = fj.Id, Name = fj.Name }).ToArray();

                //將數據緩存起來下一次用(設置一個緩存有效時間,使用絕對過時,到達指定過時時間,緩存失效)

                HttpContext.Cache.Insert(
                                          "FJIdNames",       //緩存項的鍵(string)
                                          FJIdNames,         //緩存項的值(object)
                                          null,         
                                          DateTime.UtcNow.AddMinutes(30),                 //絕對到期時間(DateTime)
                                          System.Web.Caching.Cache.NoSlidingExpiration    //滑動到期間隔時間(TimeSpan)
                                        );
            }

            //將獲得的數據轉化成json格式字符串
            string jsonResult = CommonHelper.ConvertToJsonStr(FJIdNames);

            //返回給瀏覽器的結果字符串
            return Content(jsonResult);
        }
複製代碼

 

說明:這是一個 asp.net MVC 中處理一個請求的action方法,其中有一個重要的方法

public void Insert(

  string key,                                             --> 緩存項的鍵

  object value,                --> 緩存項的值

  CacheDependency dependencies,           --> 緩存依賴項(這裏不用,後面會用,是重頭戲)

  DateTime absoluteExpiration,               --> 絕對過時時間點

  TimeSpan slidingExpiration                   --> 滑動過時時間間隔

);

 

  在這裏是利用了緩存的過時時間來對緩存數據進行更新操做,每當緩存數據通過了30分鐘後就要從新從數據庫中拿一次數據來更新緩存中的內容,來看一下執行的結果   (爲了便於展現結果,將絕對過時時間調爲30s):

第一次請求

(數據庫表中此刻的數據):

 

(執行結果):

 

第一次請求的話確定緩存中是沒有數據的,因此要向數據庫要數據;

 

 

第二次請求

(請求以前改變一下數據庫中相應表的數據)

 

 

 

 

 

(執行結果):

第二次請求,因爲沒有到緩存項的絕對過時時間,緩存中還有數據,不用向數據庫要數據,從緩存中取出來就行;

 

 

過30s後再請求

(數據庫表中此刻的數據):

 

(執行結果):

 

緩存中數據已通過期被移除,須要從新向數據庫請求;

 

 

  從以上三次請求能夠看到,最後的確是實現了緩存數據的更新。

  但一樣能夠看到這樣作有一個壞處:在還沒到達過時時間的這段時間裏,請求的數據依然是原來的緩存中數據,和數據庫中的數據並不一致。

  其中設置的絕對過時時間點要根據實際的數據刷新的可容忍度來進行設定,而剛好在個人這個應用場景中的可容忍度最不能把握,它要求的是 當數據庫中的數據改變之後,緩存中對應的數據在下一次請求結束後必定要立刻跟着改變,固然你也能夠把過時時間儘量的調小,調到一秒。固然,這樣的話仍是要頻繁的向數據庫進行請求,那不是背離了咱們本來使用緩存優化的目的了嗎?

 

  因此如今的問題是:有沒有一種方法能讓數據庫和服務器程序創建一種聯繫,這種聯繫比如是一種「心靈感應」,當數據庫表中的數據發生變化的時候,立刻就能讓服務器中的對應的緩存項「感應」到這個變化,從而讓原來的緩存項失效呢?答案固然是,有的。

 

數據庫依賴緩存,對,是它,就是它。

 

  ASP.NET 有 3 種類型的依賴:

  • 緩存項目依賴
  • 文件或文件夾依賴
  • 數據庫依賴

   本文要講的是數據庫依賴:數據庫緩存依賴是一項當數據庫中的相關數據被修改時自動使緩存的數據對象失效的技術。

  之前不知道有 數據庫依賴 的時候,有想過使用文件或文件夾依賴來實現相似於數據庫依賴緩存的功能,大概的思路就是:用某個文件做爲媒介,在進行了對數據庫表的數據改動後,同時改動一下該文件來觸發緩存的失效。還好我在看了大神們寫的博文之後,立刻中止了我「愚蠢」的想法,那樣作實際上是多此一舉,並且並不能很好的實現,有現成的數據庫依賴不用幹嗎。

 

 咱們來看一下如何使用它:

 一、配置:

  1)在當前網站mvc項目下的Web.config文件中加入

複製代碼
<!--(數據庫鏈接字符串)<configuration> 結點下配置-->

<connectionStrings> <add name="connStr" connectionString="server=127.0.0.1; user id=sa; password=root; database=LZXF" providerName="System.Data.SqlClient" /> </connectionStrings>
複製代碼
 <!--(緩存數據庫依賴配置)<system.web> 結點下配置-->
    <caching>
      <sqlCacheDependency enabled="true">
        <databases>
          <add name="LZXF" pollTime="5000" connectionStringName="connStr" />
        </databases>
      </sqlCacheDependency>
    </caching>    
複製代碼

 

複製代碼

 

  

  2)在 Application_Start() 中加入

 

 

            //配緩存數據庫依賴
            string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ToString();
            //啓動數據庫的數據緩存依賴功能      
            SqlCacheDependencyAdmin.EnableNotifications(connectionString);
            //啓用數據表緩存  
            SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, "(表名)"); //第二個參數能夠是單個表名或表名的數組

 

 

 

 二、代碼部分

 

複製代碼
        public ActionResult GetAllFJs()
        {
            //嘗試從緩存中取出數據
            var FJIdNames = HttpContext.Cache["FJIdNames"];

            if (null == FJIdNames)   //緩存中沒有數據
            {
                //從數據庫中查詢出數據
                FJIdNames = FJService.GetAll().Select(fj => new { Id = fj.Id, Name = fj.Name }).ToArray();

                //將數據緩存起來下一次用(使用數據庫依賴的緩存,當數據庫中對應的表的數據發生改變時,緩存失效)
                HttpContext.Cache.Insert("FJIdNames", FJIdNames, new SqlCacheDependency("LZXF", "T_FJs"));
            }

            //將獲得的數據轉化成json格式字符串
            string jsonResult = CommonHelper.ConvertToJsonStr(FJIdNames);

            //返回給瀏覽器的結果字符串
            return Content(jsonResult);
        }
複製代碼

 

  其中的 SqlCacheDependency(數據庫緩存依賴類) 是最重要的一個類,就是它創建起了數據庫和服務器程序之間 「溝通的橋樑」 ,

  使用它的一個構造方法:

  public SqlCacheDependency(string databaseEntryName, string tableName) 來建立一個數據庫緩存依賴類對象,傳給建立緩存項的方法Insert, 這樣來創建該緩存項的數據庫依賴,每當該指定表中發生數據的變更時都會銷燬該緩存項。

 

看一下執行結果:

  沒改變數據庫表數據以前:

 

(執行結果):

 

  改變數據庫表數據以後:

 

(執行結果):

 

改變了數據庫表的數據之後再去請求數據,請求到最新的數據,說明舊的緩存被移除了

 

 

既然都會用了,那接下來要看的就是原理,(原理,原理最重要)

 

用完了之後就會很疑惑,它是怎麼實現的呢?

思考:首先是改動了數據庫表中的數據,這一步操做之後一定要引起某種操做。在數據庫中改變表中數據會觸發操做?講的不就是觸發器嗎。

 

來看一下數據庫中多了些什麼:

打開sqlServerManagement查看數據庫發現

 

多了一個 AspNet_SqlCacheTablesForChangeNotification 表,表中內容:

 

 

要找的觸發器在這裏:

 

看一下觸發器裏面的內容:

說的就是:當 T_FJs 表中發生了 INSERT, UPDATE, DELETE 這些操做,就去執行 dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure 這個存儲過程,這個存儲過程是咱們開啓sql server的緩存依賴自動生成的

 

找一下存儲過程 dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure,在這裏:

 

內容是:

 

因此最後對原理的總結,我就引用一篇大神博客(https://www.lanhusoft.com/Article/290.html)裏的總結:

  當sql server啓用緩存依賴以後,就會在對應的數據庫添加相應的表、觸發器和一些存儲過程。它是利用觸發器來監測表的數據的變化,若是有增、刪、改就插入數據到通知表,而後通知訂閱這個通知的網站此緩存項失效。

 

最後要說的是使用緩存依賴也有限制:必須用ASP.Net和SQL Server開發應用,也就是SqlCacheDependency是基於微軟的那套體制。

 

參考博文地址:

  https://www.cnblogs.com/SkySoot/archive/2012/08/15/2640559.html

  https://www.lanhusoft.com/Article/290.html

  這是個人第一篇博文,之前想過爲何要寫博文這個問題?如今網上隨便一搜都有本身想要的內容,並且有些大神寫的很不錯。後來慢慢的發現每一次遇到問題都要上網搜博客看,並且不少時候遇到的是同一個問題,可能之前就已經思考過了,如今又要浪費時間去從頭找着看已經看過的東西,那我爲何不本身寫好了整理好了存着呢。固然,方便本身的同時,但願也能方便到正在閱讀本文的你。謝謝!

 

前端JS 與 後臺C# 之間JSON序列化與反序列化(筆記)

 

  JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。

   在 前端瀏覽器 和 後端服務器 之間一般會使用 JSON格式的數據 來進行數據交互,而JSON格式的數據在 前端Javascript  和 後端C# 語言中 最終都會以對象的形式來使用,而  JSON格式的數據在http協議中是以JSON字符串的形式進行傳輸 的,因此就涉及到JSON字符串與對象之間的相互轉換問題。

 

    

 

 

首先,咱們來看一下一個C#的類變量數據是怎麼從後端C#走向前端Javascript的。

 

    

 

源碼以下:

(C#對象  ==>   json字符串)

複製代碼
        /// <summary>
        /// Json字符轉換的配置對象,設置了基本Json配置的信息
        /// </summary>
        private static readonly JsonSerializerSettings Settings = 
            new JsonSerializerSettings {

                //忽略循環引用,若是設置爲Error,則遇到循環引用的時候報錯(建議設置爲Error,這樣更規範)
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

                //日期格式化,默認的格式也很差看
                DateFormatString = "yyyy-MM-dd HH:mm:ss",

                //json中屬性開頭字母小寫的駝峯命名
                ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
            };

        //根據配置規則獲得json轉換類
        private static JsonSerializer scriptSerializer = JsonSerializer.Create(Settings);

        /// <summary>
        /// 將任意一個對象轉換爲json字符串的表示形式
        /// </summary>
        /// <param name="obj">要轉換成json字符串的對象</param>
        /// <returns>轉換後的json字符串,失敗則返回null</returns>
        public static string ConvertToJsonStr(object obj)
        {
            try
            {
                StringWriter stringWriter = new StringWriter();
                scriptSerializer.Serialize(stringWriter, obj);

                return stringWriter.ToString();
            }
            catch
            {
                return null;
            }
            
        }
複製代碼

 

(json字符串   ==>   javascript對象)

 

var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //結果是 {a: 'Hello', b: 'World'}

 

 

 

 

而後,再反過來看一下一個Javascript的變量數據又是怎麼一步步走向C#後端的。

 

    

 

源碼以下:

(json字符串  ==>  c#對象)

 

複製代碼
        /// <summary>
        /// 將json字符串轉換成對象
        /// </summary>
        /// <typeparam name="T">要轉換成的類型</typeparam>
        /// <param name="jsonStr">json字符串</param>
        /// <returns>成功轉換返回對象,不然返回null</returns>
        public static T JsonStrToObject<T>(string jsonStr)
        {
            try
            {
                JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();

                return javaScriptSerializer.Deserialize<T>(jsonStr);
            }
            catch
            {
                return default(T);
            }

        }    
複製代碼

 

 

(javascript對象   ==>   json字符串)

 

var json = JSON.stringify({a: 'Hello', b: 'World'}); //結果是 '{"a": "Hello", "b": "World"}'

 

 

 

 

 

補充: 

   在這裏之因此不使用.NET自帶的 JavaScriptSerializer 類來進行對象到 JSON 字符串之間的轉換,是由於在解析日期格式的數據時有缺陷,而使用 Newton.json 能彌補這種缺陷。 
   其實,咱們使用Jquery進行AJAX編程的時候,Jquery提供的ajax函數已經在內部封裝了由JSON字符串轉換成JavaScript對象的機制,因此不少時候咱們並不須要本身動手實現 (json字符串 ==> javascript對象) 轉換。 
相關文章
相關標籤/搜索