Quantcast
Channel: 天空的垃圾場
Viewing all 144 articles
Browse latest View live

SQL Server - FileTable拒絕存取之問題

$
0
0

最近,連續發了幾篇SQL Server的文章,這大概也是有史以來連續最多的一次…Orz…,回歸正題,不知道大家還記不記得之前寫的FileTable文章,經過一段時間的使用,我們終於把他佈署到半正式的環境了!!

然後就發生了錯誤…Orz…但這次發生的問題一開始還覺得滿詭異的,因為使用Web Api,所以只吐回來發生錯誤…,重點是,Local開的IIS Express是正常的,完全不知道哪裡錯,後來想辦法把問題調閱出來,才發現這次發生的問題,如下圖,答案就是"拒絕存取",而詳細的錯誤訊息如下,不過大家約略看看就可以跳過了,不是重點= =+。

image

"Message":"發生錯誤。","ExceptionMessage":"類型 'MultipartFormDataStreamProvider' 的資料流提供者擲回例外狀況。","ExceptionType":"System.InvalidOperationException","StackTrace":" 於 System.Net.Http.MimeBodyPart.GetOutputStream(HttpContent parent)\r\n 於 System.Net.Http.HttpContentMultipartExtensions.MultipartWriteSegmentAsync(MultipartAsyncContext context)\r\n 於 System.Net.Http.HttpContentMultipartExtensions.MoveNextSegment(MultipartAsyncContext context)\r\n--- 先前擲回例外狀況之位置中的堆疊追蹤結尾 ---\r\n 於 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n 於 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n 於 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n 於 CSW.Controllers.API.ActivityImgController.<Post>d__0.MoveNext()","InnerException":{"Message":"發生錯誤。","ExceptionMessage":"拒絕存取路徑 '\\\\localhost\\sqldb\\FileTable\\Activities\\BodyPart_4329878c-2610-4f2d-ba16-f5ce595f603f'。","ExceptionType":"System.UnauthorizedAccessException","StackTrace":" 於 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n 於 System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)\r\n 於 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)\r\n 於 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)\r\n 於 System.Net.Http.MultipartFileStreamProvider.GetStream(HttpContent parent, HttpContentHeaders headers)\r\n 於 System.Net.Http.MimeBodyPart.GetOutputStream(HttpContent parent)"}}

好的,我們回頭看一下這次的問題,這次的問題是"拒絕存取",但Local可以正常運作,那為何佈署上去後,就不行了呢??,我想聰明的大家,應該都已經想到了!?

是的,既然問題是"拒絕存取",那就表示是因為權限不足,那為何Local又可以執行呢??( 總覺得鋪梗鋪得很像藍色蜘蛛網- -… ),答案很簡單,因為小弟執行Visual Studio是使用Administrator的權限執行,所以IIS Express也是Administrator的權限…那存取FileTable的資料夾,自然也暢行無阻。

但在現實的環境中,就沒那麼單純了,在正式的Server上,IIS並不會有最高的權限執行…( 因該也不會有人想用最高的權限執行吧… ),所以自然而然,就變得沒有權限去存取FileTable的資料夾…( 怕有人誤會,所以補充一下,這邊是代表,沒有權限使用Windows IO機制來直接存取FileTable的檔案,也就是說,沒有權限使用檔案總管來新增檔案,而不是在敘說寫入到db的權限 )

既然知道問題了,那該怎麼做呢!?,基本上,小弟也不太會XDDD,所以今天搬出了公司所有SQL Team的救兵,最後動用到許致學老師才幫忙解決…( 深深感謝大家QQ~~ )

首先,雖然權限的問題,在一般的Web應用也會碰到,但FileTable的設定權限是沒辦法從檔案總管那邊下手去設定的,因為FileTable的權限會透過SQL Server來控管,所以我們要透過SSMS來針對SQL Server的權限設定下手,簡單的說,就是把IIS的權限加到SQL Server裡面去。

首先,我們先從登入的地方,來新增一個新的登入,畢竟,要透過SQL Server,那一定要先有登入帳號阿!!,不然連SQL Server都沒登入的權限,那還有啥權限可以去讀取FileTable…

所以我們可以如下圖,按下搜尋,來把IIS的Windows帳號加入。

image

但有那麼單純嗎?當然沒有,因為新版的IIS帳號,已經變成虛擬帳號了,對於虛擬帳號有興趣的朋友們,可以參考保哥這篇文章;所以我們要加入到SQL Server裡面的是一個IIS的虛擬帳號,那帳號名稱到底是甚麼呢?就要開啟IIS來看一下,目前我們到底用到的是哪個應用程式集區;由下圖可以發現,我們用到的是ASP.NET v4.0。( IIS的虛擬帳號,會隨著應用程式集區的不同,而有不同的名稱。 )

image

所以我們回到SQL Server,就可以選擇剛剛找到的虛擬帳號,而IIS的虛擬帳號,預設是IIS AppPool\{應用程式集區的名稱},所以我們上面是ASP.NET v4.0,所以這邊要輸入IIS AppPool\ASP.NET v4.0,輸入完成後,就可以檢查名稱一下,如果無誤,就可以發現,變成了有底線的ASP.NET v4.0。

image

那真的那麼簡單嗎??當然不是那麼簡單,如果這樣就OK了,小弟也不用寫這篇文章記錄了,雖然我們上面輸入了正確的帳號名稱,但當我們按下確定的時候,SSMS又會很"聰明"的幫我們加上主機名稱…變成"主機名稱\ASP.NET v4.0",也因此,這個帳號還是不對的,所以我們還是必須手動的回到如下圖的地方,輸入正確的虛擬帳號…( 所以上圖的那個步驟,其實是可以不用做的…只是想提醒大家,因為SSMS太聰明了,所以造成了我們的困擾- -+ )

image

輸入完成後,我們到伺服器角色的地方,選擇public就可以了,也不用太多的權限。

image

接下來,使用者對應這邊,我們要讓剛剛輸入好的SQL Server登入帳號對應到有FileTable的資料庫,簡單的說,就是資料庫會對應剛剛我們建立好的SQL Server登入帳號,而這個登入帳號又會是Windows的IIS虛擬帳號… ( 真多帳號阿- - ),如下圖,印象中寫入和讀取的權限可以不用勾,但有點忘記了,如果做完還是不行的話,可以考慮再回來勾一下。( 歹勢,中間測試太多東西… ),然後就可以按下確定來建立SQL Server登入帳號,並且和資料庫有關聯了。

image

接下來,我們到FileTable的地方,並且選擇權限,我們就可以透過搜尋找到剛剛建立的SQL Server登入帳號,那這邊我給的權限也是刪除、更新、插入、選取,理論上改變應該是可以不用勾選,同樣的,如果真的不行,大家還是可以回來勾勾看。

image

這邊是插入和選取的地方。

image

完成之後,終於就可以順利的寫入進去了( 淚 )。

image

這樣,就完成了權限的設定~~

後記

最後,還是要感謝各位同事的支援,與老師的協助~~也花了大家非常多的時間…重點是,到最後帳號其實都ok,但小弟程式有誤,所以還以為不行,在那邊繞圈子…真是對不起阿~~ ( 遮臉.. ),總之,造成大家困擾了,在這邊感謝大家協助,也希望這篇文章能協助到有遇到相同困難的朋友~~


TFS - 在Web管理介面的Code增加說明與討論

$
0
0

這也是屬於TFS 2013和Team Foundation Service的新功能之一,以前我們要針對Code進行討論等等( 不是那種雙斜線的註解喔 ),我們會用Code Review的功能,但是Code Review通常是使用在未簽入之前,而且使用者可以自己選擇要給誰Review,所以並不是每個人都可以收到Review的通知。

image

另外一種情況,我們可能簽入後,才會看到Code,而也有可能會對於簽入後的Code,有些想要說明,或是討論的,所以現在新的版本,更加的強化了這個部分。

我們可以從Web的管理介面,的Code的地方進去,我們就可以針對想要了解註解的功能進行註解。

image

完成後就會如下這樣,而其他人也可以在下面回話與討論。

image

這是屬於TFS的新功能之一,雖然目前還沒有很多的應用,但相信未來官方會再針對這塊有更詳細的解說。

TFS - 新的Features Item

$
0
0

持續來看看TFS的新功能項目之一,如果有再跑Scrum之類的,可能會常常進入到Item的管理介面裡面去,而這次TFS 2013和Team Foundation Service多出了一個Features的Item。

如下圖所示,我們可以看到Features出現在左邊,而我們可以新增一個Features。目前小弟自己的看法,認為Features是在大於Product Backlog層級的Item,例如某些產品要那些特色,而這些特色裡面會在包含了Product Backlog的需求,然後再去細分為實作的Sprint Backlog( Task ),這樣分層的好處,就是可以更加得清楚,使用者到底要的是怎樣的東西。

image

而如果真的要建立的話,我們也可以發現,和之前的Product Backlog有所不同,尤其是Target Date這項,我們可以定義一個目標日期;至於為什麼會有這個選項,猜想因該也是為了讓整個專案能更加的關聯住,但小弟目前還沒看到官方提供正式的說明,所以就先不加以猜測了。

image

其次,如果點選了第一張圖箭頭的位置,還可以切換想要關注的觀點;比方說,小弟切換成Features to Backlog items時,我們就可以再從Features前面的加號,新增一個新的Product Backlog…從這邊就可以看到階層的關係。

image

最後,我們也發現Backlog Items的選項旁邊多了圖示可以點選,我們點下去之後,就可以看到Product Backlog的階層,老實說,這真的是個很方便的功能。

image

大致上到這邊。

後記

有些應用官方還沒跳出來解說該如何用( 又或是小弟沒找到,沒時間看QQ ),所以在這邊先稍微介紹一下,未來如果有知道怎樣是官方建議的應用,會在修改此文章,給大家參考,也請大家多見諒。

Visual Studio - 2013新功能

$
0
0

2013/07/18 更新

最近沸沸騰騰的其中一個項目大概就是VS 2013了,從出到現在,只有之前稍微看了一下版控的部分,IDE終於比較有時間可以玩一玩,所以就邊看教學影片邊紀錄~~,而整個看完後,才發現已經有滿多前輩朋友們,也都已經紀錄了很多文章..Orz…不過都已經截圖了…就當作是給自己的一個紀錄文吧~~

而每個功能,如果有發現有前輩有寫得不錯的文章,也會補充在下面,另外,每個功能的中文標題,都是小弟自己會意Key的,並沒有參考原文,請多見諒喔~~

首先,裝完Visual Studio後,第一個發現的應該就是出現了參考的連結。

參考

image

當我們點下去參考,VS2013就會很貼心的Show出相關的資訊!!

image

如果有三個參考,就會Show出三個=v=

image

而如果點了跳出來的資訊,就還可以看到是哪段Code參考到喔!!而且如果雙擊的話,還會直接導過去喔!!

image

好友小章哥也有介紹到這個功能~

Peek Definition (Alt + F12) 查看定義

另外,查看定義的功能也變強大了。

image

是的,它會自動地在原本的視窗再跳出來XDDD ( 超方便的啦~~ )

image

如果按下紅色框框,就會幫我們帶出大的視窗。

image

以上的功能Larry前輩有深入的介紹喔!!

接下來是顏色的設定,總之,就是多了vs2010的顏色…

image

同步功能

接下來是同步的功能,可以讓VS2013同步設定,這個對於常重灌的人,應該滿有用的XDDD

image

對這個功能有興趣的可以再參考Larry前輩的深入介紹!!

Enhanced Scrollbar 捲軸

接下來是旁邊的捲軸,我們只要在捲軸上按下滑鼠右鍵,就有選項可以選。

image

我們改成如下圖的垂直捲軸使用地圖模式。

image

那捲軸就會出現迷你版的Code,滑鼠一上去後,還可以看到放大的Code。其實這個功能VS2012的Power Tools就有了,現在終於內建進去了!!

image

不過小弟更喜歡這個,以前都裝Power Tools才有;這個功能就是會在捲軸上,用不同的顏色顯示位置,例如小弟這邊搜尋i,那旁邊的捲軸就會出現所有有i的顏色~~

image

這個功能Larry前輩Kevin哥都有介紹到~

與瀏覽器連結

這功能是當啟動偵錯的時候,會連結瀏覽器。

image

然後如果改了東西,就可以直接在VS2013裡面按下Ctrl + Alt + Enter 就會直接在瀏覽器上呈現改變,而不用去刷新瀏覽器…

image

另外,執行時期,也可以看出現在的JavaScript,並且設定中斷點。( 不過我想大家應該還是比較喜歡用瀏覽器偵錯吧0 0… )

image

偵錯時改變值

當我們針對進行偵錯,並設定中斷點的時候,當跑到那個中斷點的時候,是可以改變那行Code的,如下圖WPF的Code,原本要給的值是Test,現在在中斷點的時候,可以改成Test1111。

image

那只有WPF可以嗎??當然不是,ASP.NET MVC也行喔,我們設定return View();這行為中斷點。

image

如果是正常執行的話,應該會出現ASP.NET MVC 5的畫面。

image

但我們可以在中斷的時候改變,改成return Content(“cool”);

image

那輸出就會變成如下圖,當然Code改變後,就算停止偵錯,還是會維持Content(“Cool”),不會變回原本的View()喔!!

image

中斷的js也可以喔!!

image

Auto Brace Complete 自動產生結束括號

如下圖(此圖來自於Microsoft 官方Blog),這個功能也是Power Tools就有的,現在正是納入VS 2013裡面。當我們輸入"(" 的時候,會自動地出現右邊的括號")",不用我們在自己Key了~~( 不過小弟自己都有裝Power Tools,沒啥感覺就是了- -… )http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-92/8228.bracecompletion.gif

New IDE Features for JavaScript 新的JS IDE功能

我們直接看下圖比較快,首先,比較明顯的是,上方出現了Function Bar,可以讓我們快速跳到想要的Function,另外,如果我們點了IDE編輯室窗裡面的Function ( 例如下圖的function( selector…. ) )則上方的Function也會自動跳喔!!

image

另外,我們可以看到,我們點集了某個變數之類的,在那個Function之下,就會高亮度出來。

image

更特別的是,他只會尋找Function底下,並不會亂七八糟的亂找,如下圖,只會顯示function底下的elem,上層的elem是不會高亮度的。

image

觀看function return values

這個功能也超級實用,可以觀看Function return後的值,如下的Code,我們可以從debug下,設定中斷點,來查看,不過這邊要查看,需要有點技巧,我們必須把中斷點設定在int result那行,然後中斷到那行的時候,在按F10(或是點選不進入函式)跳到"}"的地方,就可以從目前變數那邊看到資訊喔!!

其次也可以從即時運算視窗輸入$ReturnValue也可以看到,這算是一個很不錯的功能,尤其像小弟常常接一大串的情況下,這功能就很好用~~ ( 微軟Blog說明 )

image

但如果回傳的是物件之類的,則會顯示如下圖,基本上還是可以看的到回傳的東西就是了~~

image

除此之外,還有小弟沒發現,但Larry前輩有玩出來的一些功能,例如可以程式碼分析的加強整行的拖動功能選項的尋覽內嵌巡覽等等,有興趣的可以去看看喔!!

後記

除了這幾項以外,還有幾個大功能,因為功能比較大,就不列在這篇裡面了,未來有機會,再來繼續補充完畢!~

參考網址

C# - 非同步的async和await

$
0
0

7/31 更新 – async和await是.net 4.5才出現的,感謝ALEX前輩提醒~裡面內文已經更新

前一段時間,在測試Visual Studio的非同步偵錯功能,範例是一個使用async和await滿簡單的程式,但其中有一行Code,內容是寫Task.Yield(),小弟我一直搞不太懂,所花了一點時間把async和await的底層稍微看了一下( 真的只有稍微…但花了整整一整天的時間… ),看完後,也大致上了解Task.Yield(),所以小弟也在這邊紀錄一下;雖然這次是從Task.Yield()為出發點,但實際上還是會圍繞在async和await上面。

這篇文章,大致上的內容是出處於MSDN雜誌,有興趣的可以去看看原文,而這篇文章,也不太會針對async和await的用法做太多的解釋,也請大家見諒。

首先,該從哪邊談起呢??應該還是要從非同步與同步開始說起吧,基本上,這裡不會太加以敘述這方面的概念,只會簡單的說一下,同步簡單來說,就是一步接著一步,如我們平常寫的程式碼一樣,從上而下,一步一步依照著我們的步調執行。

那這樣會遇到怎要的問題呢??簡單的說,當我們遇到了大量存取,或是要消耗大量運算的時候,會碰到怎樣的問題!??,是低,就是卡住,因為會卡在那一行的程式碼嘛…

而因此,就產生了非同步的概念,非同步簡單的說,就像時空跳躍,當我們遇到需要處理大量資料,而會卡住的時候,先跳去做別的事情,然後等那大量的資料處理完後,再接著處理那大量資料後的程式碼;如果以網頁的角度來說,同步,就好像,我們按下了一個按鈕後,然後看著圈圈在那邊轉阿轉,然後像瀏覽器當掉一樣,甚麼事情都不能做;而非同步,當我們按了一個按鈕之後,還是可以到處亂點~~ ( 其實現在網頁幾乎都在跑非同步了… )

好,其實還是花了一些時間介紹- -|||,基本上,我想非同步語同步的觀念,以現在寫前端的朋友們,應該都非常熟了才對。

那我們回來看一下早期的C#寫法( 其實也不算多早阿QQ… ),如下,我們使用MSDN雜誌的Code來進行解釋~~;其實如果會寫js的朋友,應該就很有感覺,因為語法幾乎一樣阿XDD;下面這個範例,就是TryFetchAsync會傳入網址和一個Action型別的委派( 稱為callback ),以功能面來說,就是抓取網頁資料的方法~~,然後這個方法定義了WebClient,準備抓取資料,那可想而知,WebClient一定會跑很久( 好啦,至少不會很快… ),所以如果沒使用非同步的話,就會需要等待;而這邊使用了非同步,所以會定義一個完成後的觸發事件,讓網頁下載完成後,在進入那個事件去做處理;也因此,在網頁下載的過程中,可以去做其他的事情,而不會卡在那邊~~。而這種感覺,就是小弟我前面說的,把等事情處理完後,再回來執行後面的程式碼。那當資料下載完後,就使用委派的方式,去呼叫傳進來Action型別的callback,如果成功就呼叫callback(args.Result,null),至於為什麼會這樣呼叫,是因為callback第一個型別為byte,第二個型別為exception,這兩個參數會由DownloadDataCompleted的事件處理,預設傳入的兩個參數來得知,由DownloadDataCompleted的事件處理的兩個參數為sender ( 事件的來源,也就是由誰觸發 )和args ( 事件的資料,看是成功後取得的資料,或是錯誤的資訊 )。好吧…有點離題太遠了,有興趣的可以參考msdn的這裡那裏

static void TryFetchAsync(string url, Action<byte[], Exception> callback)
{
    //使用WebClient抓取網頁資料
    var client = new WebClient();
    //定義事件,當下載完成後,執行此事件,_Sender、args是事件資料
    client.DownloadDataCompleted += (_, args) =>
    {
        if (args.Error == null) callback(args.Result, null);
        else if (args.Error is WebException) callback(null, null);
        else callback(null, args.Error);
    };
    //開始非同步方式下載
    client.DownloadDataAsync(new Uri(url));
}

當然,到了.Net 4.5開始,提供了async和await,讓使用者更加輕鬆的去處理,而且看起來和一般的Code沒啥差異,如下Code。( 一樣拿MSDN雜誌的Code~~因為小弟懶得再去想自己的Code了…請見諒阿… );基本上,功能和上面一樣,但是變得更加優雅了,我們加上了async並且用Task<byte[]>來當作回傳的型別,當WebClient抓到資料的時候,就直接回傳byte[],如果沒抓到,就回傳null。( 這邊小弟就不解說為什麼回傳用Task<byte[]>,但實際上,可以直接接到byte[]了,請見諒… )

static async Task<byte[]> TryFetchAsync(string url)
{
    //使用WebClient抓取網頁資料
    var client = new WebClient();
    try
    {
        return await client.DownloadDataTaskAsync(url);
    }
    catch (WebException) { }
    return null;
}

補充一下,當然,你也可以說,在沒使用async和await的情況下,我也可以直接把code塞到DownloadDataCompleted裡面去,的確,這樣的確也是可行,只要後續你要處理byte的程式碼不會很長…如果你後續還要對byte要做一堆的處理,那你想想看,我們要把這些東西塞到DownloadDataCompleted裡面去,不是就把整個cs檔案給塞爆了嗎…但不管怎樣,還是希望大家不要離題XDD,我們重點還是在討論async和await…其實中間的那段,可以省略不看啦0 0..

好,前面說了一堆大家都知道的東西,後續才是小弟比較重要的紀錄。

當我們使用async和await的時候,其實會產生類似如下的程式碼( 歹勢,請允許我說類似,因為底下的Code在C#下,可能是不能編譯的,但別忘了,編譯器編譯C#後,產生的是IL中間語言,恩,好吧,其實某方面也不是全對,底下的Code,IL也不能完全真的去跑,但這邊只是想用C#的語法來呈現概念,記這,這是概念~~ …P.S 同樣,Code來自MSDN 雜誌~ )

是的,底下其實是很長的,但我們分段來看吧,下面先po出全貌。

#if false // These are stubs of framework types shown in the paper

    public class AsyncTaskMethodBuilder<TResult>
    {
        public Task<TResult> Task { get; }
        public void SetResult(TResult result);
        public void SetException(Exception exception);
    }

    public struct TaskAwaiter<TResult>
    {
        public bool IsCompleted { get; }
        public void OnCompleted(Action continuation);
        public TResult GetResult();
    }
#endif

        static async Task<byte[]> TryFetchAsync(string url)
        {
            var client = new WebClient();
            try
            {
                return await client.DownloadDataTaskAsync(url);
            }
            catch (WebException) { }
            return null;
        }


    class TryFetch2
    {
        static Task<byte[]> TryFetchAsync(string url)
        {
            var __builder = new AsyncTaskMethodBuilder<byte[]>(); //建立生成器
            int __state = 0;
            Action __moveNext = null; //_moveNext委託 ( 播放 )
            TaskAwaiter<byte[]> __awaiter1;

            WebClient client = null;

            __moveNext = delegate
            {
                try
                {
                    if (__state == 1) goto Resume1;
                    client = new WebClient();
                Resume1:
                    try
                    {
                        if (__state == 1) goto Resume1a;
                        __awaiter1 = client.DownloadDataTaskAsync(url).GetAwaiter();
                        if (!__awaiter1.IsCompleted)
                        {
                        //__awaiter1未完成時,就先設定。
                            __state = 1;
                            __awaiter1.OnCompleted(__moveNext);//設定完程執行__moveNext (因為__moveNext是action型別,所以可以直接這樣寫)
                            return; //( 暫停 利用return跳出function,未來如果awaiter1完成,則會重新觸發__moveNext方法,再度進來。
                            //所以利用了這個機制,來達到"等待執行完"才會執行await後面的方法)
                        }
                    Resume1a://恢復執行
                        __builder.SetResult(__awaiter1.GetResult());//完成
                    }
                    catch (WebException) { }
                    __builder.SetResult(null);
                }
                catch (Exception exception)
                {
                    __builder.SetException(exception);
                }
            };

            __moveNext();//上面其實是在撰寫__moveNext的Function,這裡才是真正的第一次觸發__moveNext
            return __builder.Task;
        }
    }

首先,會建立兩個類別,分別是AsyncTaskMethodBuilder,這是一個生成器,到時候錯誤和Result都會利用SetException和SetResult來設定最終取得出來的結果 ( 也就是WebClient傳回來的結果 ) 並且放到Task裡面去,而最終,會利用Task來取得最終的結果。

第二個是TaskAwaiter,他會去定義一些方法,例如可以得知當WebClient是否完成,完成後要處理哪些事情、和取得完成後的資料。

#if false // These are stubs of framework types shown in the paper

    public class AsyncTaskMethodBuilder<TResult>
    {
        public Task<TResult> Task { get; }
        public void SetResult(TResult result);
        public void SetException(Exception exception);
    }

    public struct TaskAwaiter<TResult>
    {
        public bool IsCompleted { get; }
        public void OnCompleted(Action continuation);
        public TResult GetResult();
    }
#endif

接下來是重頭戲了,這邊有點攏長,請大家忍耐XDD;而這段Code也是真正後端處理的邏輯,他的步驟大致上如下。

  1. 會先建立一個AsyncTaskMethodBuilder這個類別,也就是建立生成器。
  2. 然後利用狀態機的概念,先把目前的狀態,設定為0,表示一開始。( int __state = 0; )
  3. 會建立一個新的Action委派,名稱為__moveNext。
  4. 準備好TaskAwaiter型別的變數,__awaiter1。
  5. 設定型別WebClient的變數為client ( 這應該是最簡單的一行吧0 0 )。
  6. 開始撰寫Action委派__moveNext裡面的內容 ( 實際上到這邊,也只是定義__moveNext會執行怎樣的東西罷了,不會真的去執行裡面的Code。 )
  7. 定義完後,跳到倒數第二行,也就是__moveNext();這裡。( 是的,到這邊,才真正的要開始執行步驟6定義的內容 )。
  8. 現在開始執行裡面的內容了,首先,先判斷__state是否為1 (也就是if(__state == 1) goto Resume1這行 ) ,理所當然,我們一開始的狀態__state = 0,所以就不會goto。
  9. 既然是第一次,所以這邊把WebClient給new起來了。
  10. 進入到第二個try裡面,同樣的,這邊判斷__state是否為1,如果為1,就跳到Resumela。
  11. 因為__state還是為0,所以這邊執行了要超長時間的client.DownloadDataTaskAsync,並且把取回的Awaiter,放到__awaiter1( 其實應該用指向啦,但用放到,初學者應該會比較好理解… )
  12. 接下來,用TaskAwaiter的IsCompleted來判斷,WebClient下載完了沒。
  13. 既然是要花超長時間下載,自然還沒好,所以又進入了if裡面。
  14. 而這時,就把狀態改成1了( __state = 1 ),雖然先把狀態改成1,但這時其實是還沒下載完成的喔!!
  15. 並且在__awaiter1.OnCompleted註冊了__moveNext這個方法。是的,沒有看錯,這邊代表當下載完成的時候,又會執行一次__moveNext這個方法一次,
  16. 然後就return了,表示完全離開了__moveNext()這個方法,跑去摸魚,喔,不是,跑去做其他的事情了。
  17. 當WebClient完成後,神奇的是其發生了,因為剛剛我們註冊了OnCompleted這個方法,所以當WebClient完成的時候,就觸發了__moveNext再執行一次!!
  18. 然後因為這次__state = 1了,所以就直接goto到Resume1,也不用再new一次WebClient了。
  19. 而又因為__state = 1,所以又跳到Resumela。
  20. 那Resumela那邊做了甚麼事情呢!?因為WebClient已經完成,就可以透過TaskAwaiter的GetResult取得資料,並且透過AsyncTaskMethodBuilder的SetResult,放到AsyncTaskMethodBuilder的Task裡面去。( 也就是__builder.SetResult(__awaiter1.GetResult());這行code )
  21. 最後,整個__moveNext()執行完後,就到了return __builder.Task,並且把Task回傳回去了~~
  22. 於是,整個TryFetchAsync真正的結束了~~

打完了整個步驟,感覺好像看完一部卡通一樣,有點哀傷的感覺(疑!?),但是從這個步驟中,我們就可以了解,整個底層的運作過程。

此外,過程中沒提到TaskAwaiter和Task的一些細節,這部分也請大家見諒,看看以後有機會,再把這兩個細節補完~~

class TryFetch2
    {
        static Task<byte[]> TryFetchAsync(string url)
        {
            var __builder = new AsyncTaskMethodBuilder<byte[]>(); //建立生成器
            int __state = 0;
            Action __moveNext = null; //_moveNext委託 ( 播放 )
            TaskAwaiter<byte[]> __awaiter1;

            WebClient client = null;

            __moveNext = delegate
            {
                try
                {
                    if (__state == 1) goto Resume1;
                    client = new WebClient();
                Resume1:
                    try
                    {
                        if (__state == 1) goto Resume1a;
                        __awaiter1 = client.DownloadDataTaskAsync(url).GetAwaiter();
                        if (!__awaiter1.IsCompleted)
                        {
                        //__awaiter1未完成時,就先設定。
                            __state = 1;
                            __awaiter1.OnCompleted(__moveNext);//設定完程執行__moveNext (因為__moveNext是action型別,所以可以直接這樣寫)
                            return; //( 暫停 利用return跳出function,未來如果awaiter1完成,則會重新觸發__moveNext方法,再度進來。
                            //所以利用了這個機制,來達到"等待執行完"才會執行await後面的方法)
                        }
                    Resume1a://恢復執行
                        __builder.SetResult(__awaiter1.GetResult());//完成
                    }
                    catch (WebException) { }
                    __builder.SetResult(null);
                }
                catch (Exception exception)
                {
                    __builder.SetException(exception);
                }
            };

            __moveNext();//上面其實是在撰寫__moveNext的Function,這裡才是真正的第一次觸發__moveNext
            return __builder.Task;
        }
    }

到這邊為止,大致上把整個async和await的底層補完,但大家有沒有想到一件事情!?是的,那就是Task.Yield勒!??我們引用一下MSDN雜誌的這句話。

靜態 Task.Yield 實用程序方法返回一個將聲稱(通過 IsCompleted)未完成的可等待操作,但會立即調度傳遞給它的 OnCompleted 方法的回調,就好像該操作實際已完成一樣。 這允許您強制進行調度並繞過編譯器為跳過它而進行的優化(如果結果已可用)。 您可以通過這種方式在「實時」代碼中擠出時間,同時提高並未處於空閒狀態的代碼的響應性。

簡單的說,Task.Yield會返回一個未完成的可等待操作(透過IsCompleted),但返回後,又會馬上調度OnCompleted,也因此,會立即的執行在await的下一行Code,就如同完成了await一樣,而這個狀況下,就可以在Code裡面,擠出一點時間( 雖然只是一下下,但對cpu來說,可能是很多了… )

另外,MSDN也提到Task.Yield的一個點。如下。

You can use await Task.Yield(); in an asynchronous method to force the method to complete asynchronously. If there is a current synchronization context (SynchronizationContext object), this will post the remainder of the method’s execution back to that context. However, the context will decide how to prioritize this work relative to other work that may be pending. The synchronization context that is present on a UI thread in most UI environments will often prioritize work posted to the context higher than input and rendering work. For this reason, do not rely on await Task.Yield(); to keep a UI responsive. For more information, see the entry Useful Abstractions Enabled with ContinueWith in the Parallel Programming with .NET blog.

大致上的翻譯是這樣的,您可以使用Task.Yield();來產生一個快速地中斷,來讓CPU有機會處理別的Thread,但如果當前有一個同步上下文(SynchronizationContext的對象),那Back回來後,這將繼續執行剩下的Code。然而,上下文會決定這項工作或相對於其他尚未了結工作的優先順序,而在大多數UI環境,上下文通常都會在目前的UI線程,所以往往會優先讓原本的Code高於UI輸入和UI渲染工作。出於這個原因,不要依賴於await Task.Yield(),以保持一個UI響應。

簡單的說,如果是想讓UI變快,用Task.Yield是沒用的,基本上Task.Yield還是用於提高其他邏輯上的處理…

後記

花了很長一段時間,把這些東西整理好,當然,對於整個await和async來說,這只是其中的一小部分,現階段小弟也沒力氣繼續追下去了,但相信Google也有更好的文章可以讓大家繼續研究下去,今天就先到這邊吧XDDD

參考資料

Windows Azure - 在Windows Server VM安裝中文語系

$
0
0

最近使用Azure VM的情況大幅提升,但裡面預設都是英文的QQ..每次抓完語言包,然後就熊熊給他忘記指令,然後就要去查TechNet...所以今天,就直接給他些一篇,記憶一下…另外雖然掛名在Azure下面,但其實在一般環境下,也可以使用…只是我想,一般情況下,大家應該會直接用繁體中文的安裝光碟吧…

( P.S 繁體中文語系包,需要MSDN帳號才能下載…沒有MSDN帳號的朋友們,小弟也無能為力了QQ )

ok~廢話不多說,首先,我們裝完Azure VM後,可以發現,全部都是英文的!!!

image

好吧,身為中國人,怎麼可已忍受英文呢!!? ( 大誤 ),所以現在就要先去MSDN下載語系包。

image

下載完後,我們可以先把ISO掛起來… ( 2012以前版本就不能這樣了…這時就只能在Local解開後,在把相關的檔案往上丟… p.s 遠端桌面用複製貼上的方式上傳檔案喔!! )

image

掛上去之後,可以發現裡面的這個目錄,但我們可以先不用管他,等下用程式直接指定這個目錄就可以。

image

接下來,就是關鍵了,我們可以再開始圖示上,按下滑鼠右鍵,然後執行Run。

image

接下來,輸入lpksetup,沒錯就是這個指令,小弟我一直忘記= =|||

image

接下來,就幾乎是看圖說故事了,選擇安裝。

image

這邊,我們就選擇剛剛掛上去的iso位置。

image

就可以看到我們要的語系。

image

安裝完成後,還是英文的,所以要重新設定一下,我們從控制台這邊,選擇add a language。

image

然後新增加新的語系 ( 底下出現中文(台灣)是因為小弟已經先建好了 )。

image

然後我們可以從這邊選擇中文(繁體)。

image

然後點選中文(台灣)後,在按下add。

image

接下來,我們選擇options。

image

我們選擇Make this the primary language,表示將此語言設為主要語言。( 如果沒有安裝語言包,這裡就看不到了 )

image

完成之後,我們需要先登出。

image

重新登入進來後,就是親切的中文 ( 啾咪!! )

image

不過,如果心細的朋友前輩們,可能會發現,時間還有進入畫面,或是新的使用者還是英文的!!所以我們還要進一步的細調,如下圖,我們先改成台北的時區。

image

接下來,回到語言這邊,我們要使用進階設定。

image

然後可以點選"將語系設定套用至歡迎畫面、系統帳戶及新的使用者帳戶",然後我們先改位置,把它改成台灣。

image

接下來,在換到系統管理,我們要選擇"變更系統地區設定",也改成台灣。

image

最後,我們要把剛剛的設定,複製到歡迎畫面、系統帳戶及新的使用者帳戶。

image

我們先到下面"將目前設定複製到"這個地方,並且都勾選起來,這樣,就會把語系設定複製過去了。

image

最後的重新登入,就可以看到,全部變成中文了!!!!

SNAGHTML372416

大體上就是這樣了~~

後記

當然,這也適用於一般的英文版Windows Server,也不是說只能用在Azure上,但是,我相信在Azure上大家應該都會遇到,所以這邊也稍微整理一下,給自己,這樣以後就不用東找西找啦XDD

參考資料

http://technet.microsoft.com/zh-tw/library/hh825178.aspx

Windows Azure - SQL Server in VM的一些注意事項

$
0
0

因為在準備投影片,就想說,順便整理整理,提供給大家做一個參考。

在Azure服務裡面,最簡單的服務,大概就是vm吧,而託Azure的福,原本要跪求IT賜給我們一台測試機,現在我們也可以直接利用Azure的VM來進行測試了,而這邊,就列一下,SQL Server in VM的一些注意事項。

如下MSDN的截圖,我們要控制SQL Server有兩條入,一條是從上面的遠端桌面,這應該是最簡單不過了,另外一個就是利用SSMS工具。但如同下圖所示,如果要用SSMS,就會有很多紅色驚嘆號;是的,這些東西就是我們今天要告訴大家,要開啟的!!

( 當然,這內容和自己建立的vm沒甚麼兩樣,差異大概只差在,需要在Azure vm的端點那邊,開啟一下端點,另外,預設會開啟一個比較特殊的port,在SQL Server 2014的時候;port 11435是給SQL Server 2014部屬用的。因為這個東西算是很基本的設定,所以後面的說明,就不會列的很詳細了,請見諒。 )

存取 Windows Azure 虛擬機器中的 SQL Server

第一步 使用SQL Server驗證連接到SQL Server

是的,我們要先用遠端登入登入SQL Server機器,在利用SSMS連入SQL Server後,要把SQL Server和Windows驗證的混合模式打開。

image

接下來,我們要修改sa的密碼和登入權限,如下圖 ( 請注意,這邊為了解說方便,所以直接打開sa,但真實環境下,請建立新的帳號,並且開啟特定的權限。 )

image

設定完成後,記得要去SQL Server Configuration Manager重新啟動一下SQL Server。

image

接下來,我們可以用sa登入試試看。

image

確定可以登入後,我們就可以進入下一步,開啟TCP/IP。

第二步 開啟SQL Server的TCP/IP

說到這個,小弟超久超久以前,要連SSMS,一直連不上去,就是因為TCP/IP沒開啟,所以大家記得要開啟,小弟使用SQL Server 2014的樣板,預設是已經開啟了。

image

接下來,是要開啟vm上的防火牆。

第三步 開啟VM上的防火牆

SQL Server預設的Port是1433,所以如果要用SSMS連進來,就要開啟1433的Port ( 如果有要用其他服務,也別忘了要開啟。)

image

這邊填入1433。

image

後續就照著預設值就可以了。

image

如果有特別需求,這邊可以調整,但我想,通常應該不會改變連線才對。

image

然後輸入一個可識別的名稱。

image

完成之後就會如下圖,另外,如果眼尖的,會發現預設就有一個SQL Server Cloud Adapter。

image

他的Port是11435,主要是拿來在SQL Server 2014直接部屬到SQL Server in vm用的,因為小弟是用SQL Server 2014的樣板建立的vm,所以有出現這個,至於2012的樣板會不會有,小弟就不知道了,大家有興趣可以幫小弟試試看XDDD。

image

到這邊,vm上的設定通通都結束了,接下來要去Windows Azure裡面設定。

第四步 設定Windows Azure VM的端點

預設情況下,當我們啟用Windows Azure VM的時候,就可以先選擇要開的端點了,如下圖。

image

如果當時忘記開,也可以自己從這邊打開。

image

例如下圖,我們要把11435打開,那我們可以如下圖設定;公用連接埠表示的是對外的連接,也就是外面要用11111來連入這台Server,而私用連接埠是內部用的連接,也就是說外面從11111連進來,會對應到內部的11435;這邊建議用不同的Port,才能防止攻擊,另外,也強烈建議,把平常沒用到的端點刪掉,例如Remote Desktop的3389,沒事的時候,就把它刪掉,要用的時候在建立,這樣會安全很多。

image

到這邊,我們就結束了所有設定。

最終步 在Local使用ssms登入

最後,我們再用SSMS登入就可以了。

image

這樣就可以順利連上去了。

補充

如果今天Azure的端點不是設定為1433,設定為10000的話,可以在ssms裡的伺服器名稱後面加入小逗點,再加上port,如下圖。

image

這樣就可以簡單的指定Port了。

後記

其實對於DBA來說,這真的很簡單,但隨著Azure的發展,Developer也可以簡單的建立Azure上的vm拿來測試與支援,相信對於專職於寫Code的朋友們,可能就會四處碰壁了,所以這邊也提供了這些步驟,希望能讓Developer們,使用DB的時候,不會一開始就卡住~~

參考資料

Windows Azure - 使用SQL Server的DAC來輸出資料到Azure的Blob

$
0
0

隨著時代的進步,Windows Azure的發展,現在Windows Azure和SQL Server的結合越來越緊密,而今天,我們就來看看,透過DAC的機制,來將SQL Server的資料,輸出一份到Azure的Blob,並且在從Azure的Blog佈署回SQL Server。

但在開始之前,或許大家對於DAC比較不熟,DAC主要是用來封裝資料庫的結構,至於為什麼要這樣呢?因為在正式的環境裡面,一般的開發人員不太可能會碰到正式的DB,而開發人員使用的是測試的DB,正常的情況下,通常是在Local開發,然後在佈署到測試db,但最終怎樣把修改過的結構給DBA呢??結論就是使用DAC,然後DBA拿到封裝包後,在去正式機上佈署。

而DAC通常有兩種封裝,一種是dacpac和bacpac,dacpac代表的是指封裝結構,而dacpac則會一起封裝資料,這邊使用的會是bacpac,這點大家也要注意一下。

從本地資料庫將資料輸出到Azure的Blob備份

在開始前,我們要先在Windows Azure那邊,建立一個新的Blob。

image

建立完成後,我們要進入那個Blob,然後建立新的容器;這邊的存取請選擇私用,表示只有此帳號的人可以讀取,才不會資料庫的東西被別人偷走。

image

容器建立完成後,就可以回到SSMS裡面,而要使用這個功能很簡單,我們只要在想要輸出的資料庫這邊,按下滑鼠右鍵,就可以看到選項如下。

image

接下來,我們可以看到這個簡介,我們可以看到,此精靈會幫我們匯出BACPAC ( 也就是包含資料 )。

image

接下來,我們要選擇連接,連線Azure的Blob

image

按下去後,會出現一個連接至Windows Azure儲存體的視窗,我們必須回到Windows Azure的Blob取得相關資料;回到Blob的儀表版,下面有一個管理存取金鑰,點下去後,就可得到我們想要的資訊,並且填入到SSMS的對話框中。

image

如果無誤的話,就可以取得到容器,這邊小弟的容器是亂打的test123。

image

最後,他會讓我們確認資訊,無誤後,就可以按下完成,開始匯出到Azure的Blob。

image

在處理的過程。

image

當完成後,我們回到Windows Azure的Blob看看,就可以發現到已經傳上去了。( 這邊有兩筆,是因為小弟測試了兩次。 )

image

這樣就完成了資料的備份。

從Azure Blob將資料匯入進來

接下來,我們要把剛剛的資料,匯入回本地的資料庫,這次我們選擇匯入資料層應用程式。

image

可以從這邊看到,我們還是利用BACPAC檔案來進行處理。

image

這邊的作法其實也都是一樣,所以就不多加解釋了喔~~

image

然後可以選擇新的資料庫名稱。

image

一樣有一些確認的資訊。

image

接下來,就開始處理了。

image

完成之後,就可以發現,我們新的資料庫已經匯入進來了,而且連資料也可以保留喔!!

image

到這邊,就算完成了。

後記

現在的東西,和Windows Azure的整合越來越緊密,除了從本地的DB可以透過DAC來將資料往上拋外,可想當然爾,Azure VM裡面的DB當然也是沒問題的,但更讓人震驚的是,Azure SQL Database也可以簡單的輸入與輸出資料到Blob,也讓整個應用更加的串接起來,更加的廣闊了。最後,如果想要手動輸入T-SQL來做的朋友們,也可以參考我好友Terry的連結喔!!~

參考資料


Windows Azure - SQL Database Data Sync

$
0
0

Windows Azure上,除了一般的SQL Database服務、VM服務外,還有一個非常強大的服務,那就是Data Sync,Data Sync如名子所述,就是資料同步的利器,除了可以將Local的資料同步到Azure的SQL Database外,還可以把Azure的SQL Database當作中繼點,散布到其他台的db去,如MSDN提供的下圖,我們可以看到整個架構圖,透過Data Sync,可以當作中樞,來同步所有的db。

image

那到底怎麼做呢?現在,我們就來試驗看看。首先,我們要先在Windows Azure的管理介面,選擇加入同步。

image

然後我們要先選擇"新的同步代理程式",來建立一個新的同步代理程式,這樣才能把讓Local端的機器,和Azure註冊。

image

按下去後,在設定完同步代理程式之前,我們需要先在Local端安裝同步代理程式,這樣才有人會自動地去同步這些東西。

image

目前也只有英文版可以用。

image

選擇這個來下載。

image

另外,我們可以從下載頁面,打開System Requirements看到一些要注意的事項,目前同步代理程式需要安裝SQL Server 2012 CLR Types x86和SQL Server 2012 Hared Management Objects x86的英文版( 中文版或是太新版本都不行…因為在Preview嘛… ),所以如果之前已經有安裝了,要先移除,可以參考我好友Terry的這篇文章;如果還沒裝,就去下面那兩個網址下載吧。

image

接下來,就進入安裝的步驟。

image

如果沒安裝那兩樣,就會跳出警告,而且目前裝了最新版或是中文版,一樣不行,所以請乖乖地使用英文版。

image

最後,官方也提出一個警告如下

  • Be sure that this Windows Service account has permissions to connect to all the on-premises databases you want to register with the agent.
  • Be sure that the service account has network access through network proxy and firewall.
  • If you have a network proxy ensure that the service account can connect to SQL Data Sync (Preview) service through the proxy.

To later change to a different service account you must uninstall the current client agent than install a new client agent under the new service account.

大致上的意思是說,如果要確保能連線到Database,你必須註冊,此外,也請確保此服務帳號,可以通過與訪問,而比較重要的是,如果要改變服務帳號,那必須把程式移除後在重裝;另外,當此代理程式和Azure上對應過後就不能改了喔,如果要改,也必須要先把程式移除掉。

接下來這邊,輸入服務的帳號與密碼,小弟就直接用自己的帳號了,如果是架設在正式的Server環境,就又特別注意權限了。

image

經過超長的設定與安裝,我們終於可以回到Windows Azure下,繼續設定。

image

設定完成後,我們要取得金鑰,可以按下產生,產生金鑰。

image

接下來,我們打開剛剛裝好的Microsoft SQL Data Sync Agent程式,並且輸入剛剛給的金鑰;在一次的提醒,此代理程式,金鑰輸入進去後,如果未來要改,就必須把程式移除後重裝喔。

image

接下來,選擇要註冊的DB,也就是Local的哪一個db要準備加入群組。

image

到這邊,代理程式就準備好了。

image

接下來,我們準備好代理程式後,我們要使建立一個同步群組。

image

這邊,我們開始建立一個同步群組。

image

接下來,我們要決定哪一台當作中樞,也就是資料的集散地,基本上,所有群組的資料,都會先到中樞,然後再去做散發。

image

接下來,加入要參考的資料庫,也就是說,中樞的db要散發給誰。

image

完成之後,我們可以看到,其實目前還未就緒,因為我們還沒決定要同步那些東西。

image

接下來,我們來到同不規則的地方,點選定義同步規則。

image

這邊,我們就可以則到Local端,剛剛用Microsoft SQL Data Sync Agent註冊的DB了。

image

然後就可以挑選,要同步那些Table。

image

決定之後,就可以存檔,並且同步。

image

我們可以從記錄這邊看到經過。

image

最後,如果想要讓他自動同步處理的話,我們就從設定這邊做調整,只要開啟,並且設定頻率,未來就會自動同步了!!

image

這樣就完成了Sync的機制,很簡單吧

後記

透過Sync的機制,大幅度的強化了SQL Database的可用性,我們可以透過Sync,來讓SQL Database只處理Read的部分,來讓讀寫分流,也可以透過Sync來讓全球各地的資料庫同步化,這些如果是以前,都必須花費很長的時間設定與測試,而現在只要透過SQL Sync,就可以輕易地做到了。

參考資料

Windows Azure - Virtual Network

$
0
0

其實Virtual Network很早就出現在Windows Azure的家族裡面,但是小弟一直處於兵荒馬亂的情況下,實在撥不出一些時間來好好的玩一玩與紀錄 ( 迷之聲 : 是在打電動吧!? ),而稱著這段時間,在看一些SQL Server in Virtual Machine的資料的時候,就順便也把Virtual Network給k一下了。

Virtual Network,可以說是一個重要的服務,為什麼!?,因為天與地就是靠他來聯繫,來達到混合雲的架構;其實說到這,大家應該就能體會到,( 其實看到名稱應該就可以聯想到了吧0 0.. )。是的,Virtual Network就是建築出一個虛擬的網路,來讓天與地都能加入此網路,形成一個獨立且安全的網段!!!當然,這個服務基本上是和Virtual Machine最緊密的整合( 因為都叫做Virtual!?,好啦,我知道很冷… ),我們可以透過此服務,讓我們在Azure上的VM,和本地端的Server整合起來,就像區往依樣!!

ok~說了那麼多,我們還是來實作看看吧,喔,對了,今天這個實作,基本上還不會有整合的例子,這邊只是純粹的在教大家設定喔!!另外,這篇的基礎主要來自於這邊,有興趣的也可以參考原文

好的,首先,一開始,我們就直接進入管理介面,建立一個Virtual Network吧。

image

接下來,就是看圖說故事了,我們要輸入名稱,然後要選擇"同質群組";是的,Virtual Network一定要建立一個同質群組( 或是選擇以前建立好的 );那甚麼是同質群組!?,簡單的說,就是告訴Azure,你的這些服務都是相關的,例如Cloud Service和SQL Database都是同一個群組,那Azure在建立的時候,就會讓他們當好鄰居,這樣在互相溝通的時候,就會有比較大的效益,不會有牛郎織女的情況喔!!

那下圖是第一次建立的情況,假設沒有設定過同質群組,那就需要補上地區和同質群組的名稱。

image

接下來,就是選擇DNS伺服器和VPN連線能力,基本上這邊我們都先不用Key,因為這是最簡單到不行的一個範例…,但DNS伺服器是拿來做甚麼的呢??,DNS Server是用來解析,原則上,如果沒有輸入,那Azure會自動幫我們配好DNS Server,來做名稱的解析,但這也僅限於Azure上而已,畢竟我們回過頭來想想,Azure也沒地方可以讓我們輸入新的名稱解析…,所以如果有需要自己控制,或是需要解析本地端的情況,就需要自己處理DNS Server了。

接下來是點對站和站對站的部分,因為這次我們不會做,所以也不用勾,基本上,這部分就是在處理與本地端的連線,未來會再補上這邊的教學。

image

接下來,就是定義這個Virtual Network的網路位置,老實說,現在的介面比之前的友善太多了,連IT白癡的小弟,都看得懂了0 0..,這邊你可以設定往段,不過只能設定私有的喔;我們可以從起始IP那邊設定,並且從CIDR那邊選擇要多少個數量,像小弟就是設定192.168.0.0開始,然後預計使用256個IP位置,所以系統就自動貼心地幫忙算出可用的範圍為192.168.0.0~192.168.0.255( 超佛心的啦!! )。

而當我們自定義好區段後,我們還可以再去做切割,分成好幾個子網段,而小弟這邊,就直接切一個就好了,所以子網路那邊就不動作,但有需要的人,可以再加入子網路,就可以在192.168.0.0~192.168.0.255之間在去做切割喔!!

image

按下去後,Virtual Network就建立好了~~ ( 超簡單的啦!! )

image

接下來,我們要創建一個新的VM,然後加入這個網段;當然過程中,其實沒有甚麼需要特別注意的,不過如果留心的話,會發現,如果我們建立好Virtual Network後,再建立VM,就會出現如下圖的選項;是的,我們可以從這邊選擇我們剛剛創建好的Virtual Network和子網路區段。

image

其他的建立VM的步驟,小弟就不多提了,因為都一樣。當建立完之後,從網路資訊那邊,就可以發現,已經是我們剛剛設定的192.168.0.0的區段了。

image

就這樣,第一步的體驗,就是那麼的簡單喔!!

參考資料

Visual Studio - 內建的todo list

$
0
0

這個是最近看到MSDN的一個功能,我覺得還滿有趣的,就把他在這邊紀錄一下。

我們寫Code的時候,常常會遇到一些狀況,並且寫在註解裡面,例如,要修正這個bug,這個問題還沒解決,或是這邊未來要重構,那我們可能會寫誠如下的註解。

image

但今天好玩的是,如果我們在註解前面加上todo,也就是key成//todo xxxxx,那其實Visual Studio會自動幫我們做整理與紀錄,如下圖,我們要在工作清單那邊,改成註解,就可以看到我們在Code裡面打的東西了… ( 找不到工作清單的朋友們,可以到上面Menu的檢視底下,就可以看到工作清單 )

image

這樣就結束了嗎??no,其實除了todo外還有很多東西可以用,我們可以從選項裡的工作清單發現,其實還有HACK、UNDONE可以註解;當然,也可以自己新增,但自己新增的東西,並不會同步到團隊的喔

image

基本上就是這樣,小小的一個功能,但其實還不錯用~~

參考資料

Windows Azure - Virtual Network之Point-to-Site連線

$
0
0

之前po過Windows Azure Virtual Network的基本設定,但那篇,只有講到如何讓Azure上的VM用我們想要的網段與位置,而今天,我們要再進階一點,來設定Local端的一臺電腦和Azure上的VM進行連線。

還記得以前沸沸揚揚的吵著私有雲好還是公有雲好,其實相信未來的走向,一定是混和雲架構,而要讓Windows Azure能混和本地與雲,那Virtual Network就是一個很重要的功能了,小弟我在前篇的時候,有講過如何讓Azrue的VM用我們只定的私有網段;但要達到混和雲,就必須讓我們Local的電腦能連上去,變成Azure私有網段的一員,也因此,Azure的VPN就顯得額外重用。

其實以目前的Azure Virtual Network有兩種VPN的模式來連線,一種是今天要提的Point-to-Site一種是Site-to-Site,Point-to-Site顧名思義,就是點對站,代表的是一台電腦連進這個私有的網段裡面,也是比較簡單的作法;但有的時候,可能會需要把整個公司的網段連進去Azure的這個私有網段裡面,那時,如果要一台一台去設定,應該會瘋掉吧,所以就有Site-to-Site的做法。

早期,Azure Virtual Network只有Site-to-Site,而且只能搭配貴森森的機器,但隨著Windows Server 2012的問世,現在Windows Server 2012也可以用軟體的方式來取代貴森森的機器,不過Site-to-Site的作法環境比較複雜,等小弟有時間買機器後,我們再來測試看看吧!!所以今天先來Point-to-Site,將Local的Windows Server 2012 R2連線到Windows Azure上的網段去吧!!

這邊,我們假設從新開始,當然,如果已經有一個Virtual Network,也可以直接進去設定。

image

這邊的步驟和前篇其實差不多,輸入一下名稱,而且必須要有同質群組,不明白的朋友們,就麻煩讀一下前篇了。

image

這裡比較重要的是,要勾選設定點對站VPN。

image

其餘的設定,就和前篇差不多了,選擇自己要的網段之類的。

image

因為我們有要使用VPN,所以要加入閘道子網路。

image

完成之後,我們要進去剛剛設定好的網路,去做閘道的開啟。

image

如下圖,選擇建立閘道,就可以了 ( 這裡設定時間會很久喔…. )

image

完成了Azure上基本的設定後,我們要回到Locl端來設定憑證,畢竟Azure上的網段,不能隨隨便便就給人連上阿!!所以我們從這邊開始,要一連串的設定憑證~

首先我們要用administrator的權限開啟Visual Studio的開發人員命令提示字元,通常如果有裝Visual Studio就可以從開始裡面找的到;會用到這個cmd的原因是因為,我們要下makecert這個指令,而vs的開發人員命令提示字元就已經includ了,不用我們自己去到makecert的目錄下指令。

接下來,我們要下如下的指令,而<RootCertificateName>這個可以替換成你想要的名稱。

makecert -sky exchange -r -n "CN=<RootCertificateName>" –pe -a sha1 -len 2048 -ss My
當輸入完畢後,就會在加入這個憑證進去這台電腦,到目前為止,這是設定Root憑證,到時候我們會把Root憑證傳到Azure,讓Azure知道,這是合法的。

image

成功建立後,我們可以從執行這邊輸入certmgr.msc來打開憑證管理。

image

我們可以從下圖處看到剛剛的Root憑證已經建立完成。

image

接下來,我們要利用Root憑證建立Client憑證,Client憑證會放在Client端,輸入以下指令建立Client端憑證;要注意的是<RootCertificateName>要填入剛剛上面Root憑證輸入的名稱喔,而<CertificateName>也是可以自由取名。

makecert.exe -n "CN=<CertificateName>" -pe -sky exchange -m 96 -ss My -in "<RootCertificateName>" -is my -a sha1

如下圖所示。

image

接下來,我們要透過憑證管理工具,把Root憑證輸出出來,並且上傳到Azure。( 是Root憑證喔,Client憑證不需要上傳到Azure )

image

這邊如下圖所選擇,不用匯出私密金鑰。

image

然後選擇目錄位置。

image

完成之後,我們回到Windows Azure看看,如果閘道已經開啟,會如下圖所示。

image

接下來,我們要上傳Root憑證。

image

選擇剛剛存放的目錄。

image

到這邊後,就只剩下最後一步了,我們只需要下載如下圖的VPN封裝,並把他給安裝起來。

image

安裝完成後,其實就可以從網路這邊看到VPN的連線圖示,我們只需要按下連線。

image

然後再按一次連線。

image

就可以順利連線了,連線後,我們就可以從Windows Azure的管理畫面,看到目前的連線狀況( 並不會立即呈現,要過一段時間喔 )

image

這樣就完成了Point-to-Site的連線了,有沒有很簡單啊XDD

參考資料

Windows Azure - 使用Windows Server 2012 R2 RRAS對Azure進行Site-To-Site連線-Server設定篇

$
0
0

前篇我們使用了Point-To-Site的方式,來讓單一台的電腦連線到Azure的網路,讓Local和Azure形成一個網段,而這篇呢,則使用Windows Server 2012 R2 ( 2012也可以 )來進行Site-To-Site的連線,讓Local和Azure兩地能連線,而Site-To-Site比較特別的是,我們會把這台Server當作中繼點,到時候,在這台Server底下的Client,只需要類似做pppoe(撥接數據機)的設定方式,就可以輕鬆地與Azure進行連線了喔!!

在官方,Windows Server 2012 的連線方式,是比較新的方式,早期官方推薦是使用貴森森的路由器等來進行VPN…但那貴森森的機器真的是太貴了…而後來推出了利用Windows Server 2012 RRAS連線的方式,但如果是企業用戶,還是建議買貴森森的機器,畢竟以效能等等來說,還是會比較強大 !!

而這次,小弟我利用一整天放假的時間(真的是消耗了一整天),來測試與完成設定,但這篇只講到Server的架設,後篇還會有一點點Client的設定,會分成兩篇,是因為小弟訂購的Ram還沒來…現在已經沒有足夠的Ram可以讓小弟測試另外一台了QQ….

最後,在開始之前,提醒大家一下,官方目前的說法是…"使用RRAS,不可以放在NAT之下",簡單的說,就是不可以掛在類似分享器底下,而且要有一個Public IP喔!!( 所以小弟這次直接拉了一條ADSL線,利用撥接的方式來達成… ),那以下就開始超長的設定過程了!!

安裝RRAS

這應該是最簡單的了…照著下面的圖,應該不會有啥問題。

image

這邊是一些提醒…

image

這邊當然是選擇角色型或功能型安裝啦…

image

因為小弟只有一台Server,也特別切分,所以直接選取就好。

image

這邊要選擇遠端存取。

image

選取功能這邊不用特別選取甚麼。

image

然後要進入遠端存取的設定。

image

他會提示我們,需要安裝一些東西,基本上當然就是默默接受了…. ( 除非不想裝XDD )

image

然後還需要裝上IIS。

image

一樣,用預設值就可以了。

image

確定無誤後,就開始跑跑跑。

image

到這邊,算是最簡單的步驟了….

設定RRAS

我們可以從下圖的位置,打開遠端存取管理。

image

因為是第一次,所以要執行精靈,因為我們只需要設定VPN,所以這邊指勾選VPN。

image

這邊出現一下提示的畫面…

image

我們這邊要選擇自訂設定。

image

然後選擇VPN存取,因為我們只要用到VPN。

image

然後就完成了…(是的,就完成了= = )

image

完成後,就會要求啟動服務了…

image

到這邊RRAS基本設定完成。

設定防火牆

接下來,要設定防火牆,要和Azure連線,要在防火牆的"輸入規則"那邊開啟以下幾個Port,其中1701的Port,小弟這邊預設就是開啟的了;那比較特別的Type=50,這邊不是小弟打錯啊…( 下面這也是Copy TechNet的…詳細可以看這裡 ),關於50這個協定,我們往下看就知道怎麼設定;至於其他的Port,小弟這邊就不教了…

  • IP Protocol Type=UDP, UDP Port Number=500 <- Used by IKEv2 (IPSec control path)
  • IP Protocol Type=UDP, UDP Port Number=4500 <- Used by IKEv2 (IPSec control path)
  • IP Protocol Type=UDP, UDP Port Number=1701 <- Used by L2TP control/data path
  • IP Protocol Type=50 <- Used by data path (ESP)

關於50這個協定,我們一樣從防火牆這邊新增輸入規則,只是我們要選擇自訂。

image

這邊沒甚麼特別的,反正就是全開吧。

image

就是這邊,我們通訊協定類型選擇自訂,並且在通訊協定號碼設定為50,後面幾乎就和一般的防火牆設定一樣,小弟就略過了。

image

到這邊,防火牆就設定完成了。

設定Azure的Local Network

接下來,我們要回到Azure,來增加一個Local Network。

image

按下去後,我們可以給一個漂亮的名子,然後VPN DEVICE IP ADDRESS這邊,要輸入RRAS這台機器的IP,如下圖,小弟是使用PPPOE連線,所以這邊會輸入的是PPPOE給的這個Public IP。

image

然後要輸入Local這邊的區網。

image

完成之後,我們就可以從下圖的位置看到,設定已經建立起來了。

image

接下來,要設定site-to-site

設定Virtual Network site-to-site

接下來,我們要進Virtual Netowork來設定site-to-site,下圖小弟這邊是已經先建立好了Virtual Network,然後要去改設定,但基本上,大家也不用擔心,因為這邊的設定算是簡單的,就算是新建立,勾選的內容和設定也還是一樣。

這邊,我們要勾選的是Connect The local network,並且選擇我們剛剛建立好的Local Network。

image

然後按下save,就好了~~簡單吧。

使用Azure提供的設定檔,設定RRAS

完成之後,我們就可以回到Azure Virtual Network得主頁面,來建立Gateway( 選擇CREATE GATEWAY ),這邊提醒大家一下,這個建立的過程非常的久,久到快要和部屬Cloud Service一樣久,小弟大概等10~20分鐘吧,所以這段時間,大家可以伸伸懶腰,洗洗澡~~;當完成之後,我們就可以下載設定檔( Download VPN Sevice Script )。

image

這邊,就有很多的設定檔可以下載,我們這次是使用Windows Server 2012 R2,所以這邊就選擇使用2012吧。

image

下載後,小弟看到一些文章,說要改這個設定檔的內容,但小弟下載後,都是已經調整好的內容,但為了怕有個萬一,還是在這邊紀錄一下。

第一,將設定檔裡面的<SP_AzureGatewayIpAddress>取代為Gateway IP Address,而Gataway IP Address在下圖框框這裡。

image

第二,將<SP_AzureVnetNetworkCIDR>取代為Windows Azure VNet的Address space,位置如下圖。

image

第三,將<SP_PresharedKey>取代為Shared Key,位置如下圖。

image

完成之後呢,把原本設定檔的附檔名,改成.ps1,然後我們就可以開啟PowerShell來執行(不是cmd阿… ),如下圖;基本上,那個設定檔會自動地幫我們把RRAS給設定好;而紅色的錯誤是正常的,因為有些東西我們之前就已經先設定好了。

image

另外,小弟在過程中,執行shell時,有發生以下錯誤。

因為這個系統上已停用指令碼執行,所以無法載入 C:\VpnDeviceScript.ps1 檔案。如需詳細資訊,請參閱
about_Execution_Policies,網址為 http://go.microsoft.com/fwlink/?LinkID=135170。

如下圖。

image

如果遇到此問題的朋友們,可以輸入此指令Set-ExecutionPolicy Unrestricted,那是因為限制規則的關係,我們可以先暫時解除。

image

當執行完上面RRAS的設定檔後,可以再下Set-ExecutionPolicy restricted來復原。

image

到這邊,終於把所有的設定給設定完成了!!

開始連線

接下來,我們就可以按下CONNECT了,這樣Azure就會開始與我們Local進行連線;如果你發現Azure告訴我們已經成功了,但是畫面還是如下圖一樣,是沒連起來,那是正常的;有時是因為時間差;但有時是真的連不到…所以,比較好確定的方法,還是從RRAS裡面來看。

image

要從RRAS裡面來看,我們可以先從遠端存取主控台這邊進來。

image

如果成功連線,我們就可以從下圖的位置中看到已連線;而如果這邊寫沒有連線,就要開始檢查IP是否正確,等等的設定,也是最耗時的… (所以可以確定,小弟今天人品不好0 0 )

image

過一陣子後,就可以發現Azure這邊的圖也已經更新完成了。

image

最後,小弟這邊在Azure上開了一台VM,並且使用Virtual Network,然後Local這邊的RRAS連上去後,我們就可以看到如下圖,透過網芳直接的存取。

image

基本上到這邊,Server端就算設定完成了!!(沒力氣寫後記了… )

參考資料

Windows Azure - 在Azure上建立SQL Server AlwaysOn需要的容錯移轉叢集

$
0
0

會出現這個主題,主要是因為最近在使用SQL Server AlwaysOn,而AlwaysOn需要架設在Windows Server Failover Clustering Cluster之上,如下圖;而又因為目前的環境全部都在Azure下,所以這篇主要是從Azure下的角度去建立,但基本上,和在Local環境下並無甚麼不同,另外,如果有興趣的朋友,也可以考慮使用Azure Virtual Network來建立混和雲的架構,而基於著個因緣,小弟就只能動手開始架設,並且做個紀錄。

P.S 這篇的建置文,主要是為了符合SQL Server AlwaysOn的架構,如果想真的學習容錯移轉叢集,請參考TechNet。

在開始前,需要提醒大家,如果要在Azure上架設WSFC,要先建立Azure Virtual Netowrk,而且也必須要有一台AD Server,建議是將此AD Server也放在Azure,如果要放在Local,則就必須利用Virtual Network的Site-To-Site或是Point-To-Site來進行VPN的連線;另外在Azure的VM,如果有設定Virtual Network,它會自動跳號,而每個IP會對應到前端的LB,所以Private IP是不可以改的!!(改了話,遠端就登不進去了- -+),所以請特別注意。( 總之,都不是件輕鬆的事情啊- -… )

如果是要在Local端建立,就輕鬆許多,只要有AD,然後有兩台Windows Server,就可以完成。

那接下來就是開始設定,這台的環境,目前還沒加入AD,後面會提到;雖然還沒加入AD,但還是可以先安裝,另外,因為叢集需要兩台以上,所以兩台都要記得安裝;當然,如果想先加入AD,也是可以,但要注意,在Azure上不可以改Private IP!! ( Local就沒差了~~ )

基本上就是從新增角色及功能精靈開始。

image

基本上沒有特殊的架構下,通常都直接選擇目前這台Server…(如果有特殊架構的人,我想大概也不會看這段安裝吧QQ )

image

這裡勾選應用程式伺服器。

image

然後功能的地方,選擇容錯移轉叢集。

image

這裡沒啥特別的,就按下一步吧。

image

角色服務這邊把分散式交易底下的那三個全部勾選。

image

關於加密憑證的部分,就先不用吧,未來有機會小弟再補上。

image

確定無誤就按下安裝吧,然後就祈禱人品ok~。

image

完成之後,就可以從工具那邊選到容錯移轉叢集管理員。

image

是的,就如前面所說,要使用容錯移轉叢集,必須要有AD,而且要把此電腦加入到AD之下,而且要用AD的帳號登入後,才可以開啟此管理員。

image

所以我們先來加入AD吧,首先我們要先設定網路IP,如下圖,在Azure下,請自動取得IP位置;而DNS伺服器的位址請使用AD那台IP( 是的,小弟AD那台IP是10.0.2.4 )。

image

接下來就是加入網域,這應該就不用教了吧~@@~

image

當加入網域的時候,會跳出要我們驗證,而這邊要注意一下,如果在Local,我們網域驗證這邊會使用STUDY4\Administrator的方式做登入,但在Azure上,如果你當初開啟的VM,設定的名稱為sky,那你安裝完AD後,sky這個人也會被加入到網域Admin的群組,所以,我們可以用STUDY4\sky來認證。( 在Azure下,STUDY4\Administrator理論上會登不進去,因為我們在創建VM的時候,根本沒設定密碼阿XDDD )

p.s 兩台都要加入網域喔….

image

加入網域後,我們可以先驗證設定。

image

就如遊戲一樣,都會有個開頭畫面。

image

接下來,我們要選擇準備要加入的Server,就如我所說的,這次是為了SQL Server AlwaysOn來的,所以我已經先準備好了兩台SQL Server;我們可以選擇瀏覽來進行選擇。

image

接下來,我們就執行所有測試!!

image

一樣,一個確認畫面。

image

然後經過一段時間的測試後,就會跳出警告…Orz…不過還好,畢竟我們是要用於SQL Server AlwaysOn AG層級的東西,所以她這邊的警告是可以忽略的。

( 這邊主要會有兩個大項警告,一個是沒有設定Share Storage,不過SQL Server AlwaysOn AG原本就不用Share Storage;另外一個是警告我們只有單張網卡,所以我們也可以忽略 )

image

確認無誤後,我們就可以開始建立叢集。

image

這邊可以選擇一個漂亮的叢集名稱。

image

接下來就是確認,看看有無錯誤。

image

到這邊就已經完成了,當然還有一些警告,但這些警告可以忽略。

image

完成之後,我們可以從 AD那台的Active Directory使用者和電腦這邊,看到剛剛我們建立的叢集已經完成。

image

另外,我們也可以從容錯移轉叢集管理員這邊,看到已經建立完成;另外,注意一下,如果下面這邊顯示失敗,又是在Azure的環境下,那有一種可能是把叢集網路設定成DHCP,那我們可以從左邊的網路、叢集網路1這邊,進去後,給他一個靜態的IP;然後再啟動,應該就可以完成了。

image

到這邊,符合SQL Server AlwaysOn的叢集就完成了。

後記

這次多虧了好友Cary的Blog的支援,如果有興趣想詳細了解的朋友們,也可以參考他那篇文章,內容有詳細的講到Share Storage等等的資訊。

參考資料

ASP.NET MVC - Web API OData Batching 406 Not Acceptable 錯誤

$
0
0

這篇稍微簡單的紀錄一下,浪費掉我打電動認真陪家人的兩個放假天,那話也說在前面,根據查到的狀況,看起來,應該是Web API的BUG,但官方並沒有承諾甚麼時候會改好,只能誠心祈禱RTM的Web API 2能順利修正,所以,未來如果有遇到類似的問題,大家可以試著升級成最新版本看看。

最後,和這件事以外的另外一個補充,先不論這件事情,目前Web API OData的支援程度還是有很多地方沒完整實現,所以很容易踩到地雷,當然,官方還是在努力地將Web API越做越好;而如果害怕擔心,對於WCF又已經熟到不行的朋友,那可以考慮直接用WCF時做OData Endpoint吧=v=。

那這個問題是甚麼??..

主要是小弟在整合OData方案的時候,搭配JayData和Datajs來協助對OData Service來進行資料的管控與存取,一般的使用上,都沒遇到甚麼多大的問題 ( 也吃了不少苦….因為現在文件幾乎都是針對WCF… ),但最近在處理以下Code的時候,缺發生了一個比較棘手的問題;喔,對了,看不太懂此Code沒關係,簡單的說,我就是要利用JS來新增資料,先用add去新增到Context,然後再用JayData的Framework來saveChanges方法,一次更新。

var CustomerAgreementType =
    new InternalIMS.Model.CustomerAgreementType({ CustomerID: fkID });
CustomerAgreementType.ModifyDate = Date.now();

mydatabase.Agreement.add(model);
mydatabase.CustomerAgreementType.add(CustomerAgreementType);

mydatabase.saveChanges(function () {

});

上面那個Code看不懂其實沒關係,總之,我想要的效果,就是利用一次的Request,來送出兩個新增的訊息( 以前的話,要送出兩次Request來達成新增。)

而之前的Web API連此功能都沒有…Orz..在Web API 2也已經提供了此功能,此功能就稱為Batching,有興趣的朋友,可以看這篇架設。(其實也只是多設定一行而已…)

但真正的問題在後面,我們先來看一下,要新增兩筆資料的Requst,如下圖,我們可以看到一次發送兩筆POST ( 因為我們要新增嘛… )

image

但當我們看Response的時候,我們可以看到發生了406 Not Acceptable錯誤。

image

當下發生這個錯誤,真的是把我搞死…後來才查到,原來是OData服務網址的錯誤,也就是這張圖的這個地方。

image

是的,其實是URL錯誤,上圖的URL的位置其實是http://localhost/Agreement和http://localhost/CustomerAgreementType,但實際上,我們的位置卻應該是在localhost/OData/Agreement之下…所以會返回406錯誤。

為了驗證真的是這個問題,所以小弟我直接用datajs來進行測試,Code如下。

OData.request({
    requestUri: "/OData/$batch",
    method: "POST",
    data: {
        __batchRequests: [
            {
                __changeRequests: [
                  { requestUri: "/OData/Agreement", method: "POST", data: model }
                ]
            },
            { requestUri: "/OData/Agreement", method: "GET" }
        ]
    }
}, function (data, response) {
    alert("ok");
}, function () {
    alert("request failed");
}, OData.batchHandler);

結果就很順利…我們可以看到POST後的網址已經正確了。

image

而Respose也正常了。

image

所以到這邊,就可以推測是這裡的問題了。

至於解法,目前小弟我查到的訊息,除了等Web API更新以外,要不就是自己重新定義處理器。

處理器的Code如下。( 此Code來源於JayData論壇的Fenderbender神人 )

public class PathFixODataBatchHandler : DefaultODataBatchHandler
        {

            public PathFixODataBatchHandler(HttpServer httpServer)
                : base(httpServer)
            {
            }

            public override async Task<IList<ODataBatchResponseItem>> ExecuteRequestMessagesAsync(IEnumerable<ODataBatchRequestItem> requests, CancellationToken cancellationToken)
            {
                if (requests == null)
                {
                    throw new System.ArgumentNullException("requests"); // Error.ArgumentNull("requests");
                }

                IList<ODataBatchResponseItem> responses = new List<ODataBatchResponseItem>();

                try
                {
                    foreach (ODataBatchRequestItem request in requests)
                    {
                        fixRequestUri(request);
                        responses.Add(await request.SendRequestAsync(Invoker, cancellationToken));
                    }
                }
                catch
                {
                    foreach (ODataBatchResponseItem response in responses)
                    {
                        if (response != null)
                        {
                            response.Dispose();
                        }
                    }
                    throw;
                }

                return responses;
            }

            private void fixRequestUri(ODataBatchRequestItem request)
            {
                foreach (HttpRequestMessage req in ((ChangeSetRequestItem)request).Requests)
                {
                    var oldUri = req.RequestUri;
                    var newUriBuilder = new UriBuilder(oldUri);
                    newUriBuilder.Path = "/odata" + newUriBuilder.Path;
                    req.RequestUri = newUriBuilder.Uri;
                }
            }
        }

其實重點就是後面,將path加上"/odata"。

然後我們在Web API的Router Config再來調整一下,改用上面的Class。

config.Routes.MapODataRoute(
    routeName: "ODataRoute",
    routePrefix: "odata",
    model: GetModel(),
    //batchHandler: new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
    batchHandler: new PathFixODataBatchHandler(GlobalConfiguration.DefaultServer));
config.EnableQuerySupport();

這樣就可以了~~

後記

目前查出來的文章,都指向ASP.NET WEB API的問題XDD,因為除了JayData外,BreezeJS也有同樣的問題;但WCF下,就無此問題;但不管怎樣,有用到此技術的朋友們,可以稍微注意一下喔!!

參考網址


Microsoft TechDays 2013

$
0
0

10/06 Update SQL Server影片已經放到最下面,有需要的可以略過上面這些碎碎念XDD,直接看最下面的影片。

TechDays已經是小弟我每年必定參加的年度大拜拜了,甚至以前要去新公司面試時,對方主管問我,有沒有甚麼要問的問題,我一定會必問的問題就是"每年我可以請假三天去TechDays嗎?";而到今年2013,小弟也已經第四年參加了這個隆重的聚會,而每次的TechDays,都是小弟一次又一次的目標與轉淚點。

記得第一次的TechDays,由各個神人前輩們給小弟的震撼,體驗到,來上技術課程是那麼的充實與愉悅,也決定每次都要來。

記得第二次的TechDays,小弟與神人們的第一次接觸…( Orz,不是ET那種接觸啦.. ),更加的決定,自己以後也要站上這大舞台。

記得第三次的TechDays,從MVP和社群的角度出發!!

而這次,第四次的TechDays,小弟終於圓了夢,站上了TechDays的大舞台上。

所以,今年的TechDays,雖然忙到快要死掉,但對小弟來說,也特別有意義。

而今年,小弟一樣又來參加了這個聚會,而且這次不用再特別請假XDD,公司讓全公司的同仁一起參加去!! ( 根本就是變相的員工旅遊嘛= =… )

一樣,每年都必定要拍的一個看板,而今年Study4.TW也一樣很榮幸的,參加了合作社群的攤位~

IMG_1778

既然是合作社群,所以小弟前一天,還是要到場看一下攤位狀況,並且測試機器,而今年,我們攤位終於不是躲在1F的後方,而是移到了2F的位置;而台灣最大的SQL PASS社群,這次也由百敬老師和Terry哥坐鎮,擺設了SQL Server問答攤位區XDD ( 說到這個,SQL PASS後面那箱帽子,快讓我的半條命去了- -… ),而當天抵達後,現場還在施工…

IMG_1756IMG_1757

完成圖如下,到了正式開始的那天,整個氣勢都出來了!!而這次少了IT幫幫忙等社群,只剩下我們三個了 QQ…

SONY DSC

而我們攤位,一樣贈送的贈品還是去年的書籤…

SONY DSC

當然,還有印製新版的書籤…沒辦法,我們是公益社群,後面沒有經費QQ…很難和一般大廠,闊氣的拿出高貴的贈品…,另外,順便偷拍一下百敬老師,和他那傳說中的超重量級筆電…

SONY DSCSONY DSC

今年的水一樣有貼上TechDays的標籤喔!!

SONY DSC

比較可惜的是,今年比較沒甚麼機會去逛攤位… ( 完全沒空…QQ.. ),而今年,主要就是平板的Surface為主 (其實說Surface為平板也不恰當…畢竟他的硬體可是媲美一台筆電… ),然後一樓一樣有超大型海報…

SONY DSCSONY DSC

而今年的主題,主要就如1F的旗子一樣,有Office 365、Windows Azure,和超熱的Visual Studio 2013和Windows Server 2012 R2。( 當然Win 8.1也是主力啦!! )

SONY DSCSONY DSC

就如小弟說的,今年沒時間去逛攤位,也沒時間收集神人照幫大家拍照;第一天剛好在樓下遇到Ruddy老師和ChiaChi,所以就順手一拍XDD,至於Ruddy老師就不用說了…業界資深之程度,除非老師退休去騎腳踏車外,大家要超越大概也很難了吧…至於ChiaChi…每次他說很簡單的問題,一定都是不簡單…。

SONY DSC

Ruddy老師這次講了三場,老實說,場場都爆滿,更厲害的是,能把沒甚麼技術的Yammer,講出有深度,有涵量,這真的不是一般人能辦到…結果Yammer那場不但爆滿到位置座不下,更體會到…甚麼是24hr的工作方式XDDD

IMG_1777

第一天的主會場,和第二天的VS發表會,這次Microsoft也是一樣重裝上陣,小弟我也可以看到Dann哥,在這次的TechDays很努力地推廣Scrum,希望能讓台灣的軟體,更上一層樓。

SONY DSC

當然,身為VS和TFS工具台灣之神的Franma ( 肥馬 ),也負責了TFS的部分~,而比較有趣的是,這次TechDays請到宋少卿來幫忙主導過程,老實說,有了相聲高手來助陣,這次TechDays也多了一分趣味,而非那麼死板的技術呈現( 只是不知道花了多少錢- - )。

IMG_1775IMG_1763

其實,就如前面說的,這次活動,小弟大概就只拍這些照片了…也沒時間趴趴走了。

最後幾張照片,用來紀念小弟自己的里程碑….這次TechDays也收集到了三大證,尤其是中間那張,更是小弟夢寐以求的~^^~

SONY DSC

而這次擔任講師,也很感謝Microsoft官方的邀請,還有Tom哥的推薦,讓我可以站上舞台上,講Azure上的SQL Server和SQL Database,而為了這次的活動,也順便把Macbook順便升級一下Ram…變成16G的筆電…. ( 因為8G跑不動了QQ ),此外,我想我也是少數不怕死,拿著Macbook上台講課的講師之一QQ…. ( 其實我是要證明,Microsoft現在不是以前的封閉了!! (點頭無誤))

IMG_1748

當然,這次的準備過程中,其實還是有很多不滿意的地方,例如,講課內容的重心在Developer上,但準備的方面還是著重於SQL Server AlwaysON和SQL Database,比重的拿捏還是沒有拿捏得很好;其次,這次的Demo也比預期的少很多,梗的鋪設也比較少…

但這也是有原因的,因為被"本次大會最有梗"之神人Eric拍了一下,所以身陷了TechDays魔咒…這個魔咒的出處。是因為中午吃飯的時候,Eric哥和我說…他準備這次TechDays,VS2013出了一堆問題、Azure出了一堆問題,所以我就和他說…你著個賽人,離我遠一點…然後他就拍了我一下,然後也拍了Demo哥一下…於是我們就深陷魔咒之中…

我遇到的狀況,建立好的OS,整個給我掛掉,掛掉就算了,大不了重建,結果Azure不給我重建…於是整個搞了三天,講課前一天我甚至沒睡覺,最後掏出自己的信用卡,講課當天早上,才把Demo復原…所以,未來還有機會…一定要先準備好錄好影QQ…

至於Demo哥…據說他上課的時候VS2013一直當掉…甚至講完課後,整個筆電掛了…Orz…

這樣就結束了嗎??..No…還有Dino哥XDD,當天他也是吃飯名單之一,他是在Review投影片的時候,不小心誤刪…不過他做的比較遠,所以波及比較少XDDD

在來是Franma,據說當天Eric哥站在Franma後面,Franma就在Demo前,服務起不來..

最後是KKBruce,Eric哥第三天拍了他之後,全桌鼓掌XDDD,然後KKBruce有一個Demo就不來了…

最後,附上這次最神之八卦神人,Eric哥的照片….感謝他,讓我這次Demo做了N遍….

SONY DSC

但不管怎樣,還是以傳說的David老師,最為傳說XDD

當然,以上歸八卦,不果魔咒怎樣的,自己還是要多多檢討這次的缺失和講不好的地方,讓自己更加精進~~

最後,這次還是要感謝Microsoft長官們、邀約的Tom哥,讓我一圓站上舞台的夢想、公司老師老闆們的支持、Study4.TW的朋友們、MVP Group前輩們的鼓勵,小朱前輩的盯場QQ、講課當天陪著我的Terry和James和Justin,中午幫我買便當的Franma,放棄去聽百敬老師、David老師、KKBruce,而願意來聽課的大家們,還有在坐月子,忍受我整個連假一直在調整投影片和Demo,忍受我徹夜不睡覺敲敲打打的老婆和兒子"們" ( 另外一個剛出生,可能感覺不到XDD ),謝謝大家!!!~

最後的最後,附上在課堂上說要給大家看得,一鏡到底,未剪輯的Azure SQL Server AlwaysON安裝過程…,這個安裝過程是當天早上安裝的流程,所以滑鼠也會不斷閃動,也請大家見諒,最後,還是謝謝大家的支持,謝謝。

謝謝大家,TechDays 2014再會~~

Windows Azure - 使用Visual Studio對Cloud Service進行偵錯

$
0
0

最近這段時間真的是超級無敵忙,所以一直到現在,才比較有空產出一些文章,而最近,也因為比較有空閒一點,所以想趕快把Azure前一段時間發佈的一些東西給補齊…

好嚕,廢話不多說,今天來稍微看一下Windows Azure SDK 2.2搭配Visual Studio的一個新功能;就是遠端進行偵錯…

是的,遠端偵錯阿… ( 遙望…. ) 令人多麼需要的一個功能…老實說之前在還沒有這個功能的時候,真的會讓人發瘋,雖然有的時候在Local都測試完成,再加上Unit Test,但上去之後,就是給他錯…所以今天出現這個功能,真的要謝主隆恩…Orz…

廢話不多說,我們盡快的給他看一下吧!!

首先,這個功能要在佈署前先設定,所以我們要進去發行這邊。

image

然後組建組態要設定為Debug。

image

並且勾選啟用所有角色的遠端偵錯工具。

image

修改完成後,就發布吧。

image

然後就要等一段無敵長的時間,不過這是沒辦法,畢竟是Cloud Service,人家可是把整台VM給重建…這樣想,感覺有沒有比較快一點XDDD

佈署完成後,我們可以先設定要偵錯的中斷點。

image

接下來,我們打開伺服器總管,是低,安裝SDK 2.2後,現在很多事情都可以從VS2013裡面進行控管了… ( 不過小弟還是喜歡進去Web管理畫面… )

打開之後就可以看到出現了連結偵錯工具!!

image

如果沒有執行一開始的步驟,是沒有的~~

image

按下去後,就會讓vs2013進入偵錯模式,然後我們就可以打開網址,進行偵錯嚕!!

image

這個功能真的是佛心來的….

後記

也別忘記,佈署到正式環境後,要把此功能關掉喔!!

參考網址

Windows Azure - 使用Visual Studio對Web Site進行偵錯

$
0
0

前一篇,我們使用VS對Cloud Service進行偵錯,那Web Site呢??是不是也是心癢癢!?其實Web Site也是可以的,而且方法一樣,所以我們這篇,就針對Web Site進行偵錯吧!!

P.S 因為SDK 2.2後,發行更加的方便,所以這邊就順便紀錄一下發行的步驟;如果是急著想知道如何偵錯的朋友們,只要注意,發行Web的設定的地方,要選擇Debug,然後最後連線到Web Site就可以了;那我們繼續看下去。

首先,我們可以選擇匯入。

image

是低,如果有Windows Azure帳號,這邊就可以選擇新增一個新的Web Site喔!!

image

其實這邊的設定和Azure在Web上的管理介面沒啥兩樣,新增需要的資料也是一樣的。

image

完成之後,就可以按下ok繼續… ( 話說回來,為啥會取名為ok勒- -…通常不是都稱為完成嗎… )

image

這邊的連線設定基本上都不需要改。

image

重點是這邊,要選擇debug!!

image

然後發行就可以了。

image

發行之後,和Cloud Service一樣,我們要從伺服器總管選擇Web Site,然後再附加偵錯工具。

image

按下去的霎那!!!VS就很貼心的幫我們打開瀏覽器,然後就可以開始偵錯嚕!!

image

還真簡單啊QQ…

後記

還是老話一句,偵錯完成後,別忘了改回Release喔!!

參考資料

Windows Azure - 使用Cache Service來讓Web Site網頁有快取效果

$
0
0

在Windows Azure上,要擴充網站,第一個遇到的問題就是存放Session,在Windows Azure的歷史上,從存放Session到Share Cache ( 2014停止支援 ),然後還有存放到Table Storage (官方也不建議了),然後到Azure SQL Database,然後Cloud Service上的Cache機制…

而雖然Cloud Service上的Web已經有解了,但是Web Site還是只能快SQL Database撐著;而如今隨著時代的演進,Azure上也提供了Cache Service (其實已經提供一段時間了…Orz… )

那今天我們就利用Cache Service來存放網頁的page,來達到提供網站的效能吧!!

首先,我們要先建立一個Cache Service。

基本上,如果沒有特別需求,選擇Basic就夠了…但如果想嘗到Cache的HA,那就必須選擇高階的選項 (最低從5G開始),而如果想要有通知功能,至少也要有中階…簡單的說,口袋不夠深,只選擇Basic,就真的只提供Cache….

image

嗯,小弟的口袋本來就不夠深,所以只能先嘗試看看Basic,看看未來有沒有人願意提供摳摳,小弟再來嘗試看看比較高階的應用XDDD

Cache建構的時間比較久,幾乎可以泡完一碗泡麵….而建立完成後,如下圖,就可以點進去做一些設定。

image

我們進入Configure裡面,就可以針對Cache進行一些設定,例如時間等等…而這邊因為沒有啟用高階或是中階的功能,所以也不能設定通知和高可用性QQ…. ( 未來有需要測試,再來設定看看吧… ) 另外,也因為是Basic,所以只能定義一組,如果是其他等級的,就可以定義10組以上的Cache設定,給不同的狀況下來使用。至於這些詳細的設定,目前MSDN也提供中文的敘述了,就直接貼給大家當作參考吧 !!~

image

接下來切到Scale底下;如果有需要,也可以從這邊進行一些設定,切換成中階的Cache或是高階的Cache,基本上,這是給有錢人看的…哭哭…

image

大致上就這樣,接下來,我們就來看看ASP.NET MVC上,怎樣使用Cache。

首先,我們還是要用老朋友NuGet來取得套件;這邊當然就是Windows Azure Cache了~

image

完成之後,會自動幫我們加上一堆設定檔在Web.config上,但我們還是需要調整一下Web.config。

image

調整的內容如下,我們要把<caching>區段的註解拿掉,然後在<autoDiscover>裡面的identifier屬性輸入Caching的url,並且把<securityProperties>區段的註解拿掉,並且在authorizationInfo裡面也填入金鑰。

基本上如下圖;另外因為這邊沒有使用到將Session存放到Cache的功能,所以<providers>的區段我們就維持註解。

image

另外,這邊也補充一下Web.config對應的關係其實是如下圖所示。

image

這邊是完成後的Web.config,金鑰的地方已經被小弟改成Key了,別忘了要輸入自己的Key喔!

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請瀏覽
  http://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <configSections>
    <section name="dataCacheClients" type="Microsoft.ApplicationServer.Caching.DataCacheClientsSection, Microsoft.ApplicationServer.Caching.Core" allowLocation="true" allowDefinition="Everywhere" />
    <section name="cacheDiagnostics" type="Microsoft.ApplicationServer.Caching.AzureCommon.DiagnosticsConfigurationSection, Microsoft.ApplicationServer.Caching.AzureCommon" allowLocation="true" allowDefinition="Everywhere" />
  </configSections>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
     <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  <!-- Windows Azure Cache session state provider --><!--<sessionState mode="Custom" customProvider="AFCacheSessionStateProvider">
      <providers>
        <add name="AFCacheSessionStateProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" applicationName="AFCacheSessionState"/>
      </providers>
    </sessionState>--><!-- Windows Azure Cache output cache provider --><!--Uncomment this section to use Windows Azure Cache for output cache-->
    <caching>
      <outputCache defaultProvider="AFCacheOutputCacheProvider">
        <providers>
          <add name="AFCacheOutputCacheProvider" type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache" 
               cacheName="default" dataCacheClientName="default" applicationName="AFCacheOutputCache" />
        </providers>
      </outputCache>
    </caching>
  </system.web>
<dataCacheClients>
    <dataCacheClient name="default" isCompressionEnabled="true">
      <!--To use the in-role flavor of Windows Azure Cache, set identifier to be the cache cluster role name -->
      <!--To use the Windows Azure Cache Service, set identifier to be the endpoint of the cache cluster -->
      <autoDiscover isEnabled="true" identifier="test12.cache.windows.net" />

      <!--<localCache isEnabled="true" sync="TimeoutBased" objectCount="100000" ttlValue="300" />-->
      
      <!--Use this section to specify security settings for connecting to your cache. This section is not required if your cache is hosted on a role that is a part of your cloud service. -->
      <securityProperties mode="Message" sslEnabled="false">
        <messageSecurity authorizationInfo="Key" />
      </securityProperties>
    </dataCacheClient>
  </dataCacheClients></configuration>

接下來,我們要用asp.net mvc程式來測試一下,這邊我們在整個Action上面加上OutputCache輸出,並且另用Duration參數設定為120秒。

using Microsoft.ApplicationServer.Caching;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
        [OutputCache(Duration = 120, Location = OutputCacheLocation.Server, VaryByParam = "none")]
        public ActionResult Index()
        {
            ViewData["Date"] = DateTime.Now.Millisecond;
            return View();
        }
    }
}

原則上,設定完後,就會有效果了,但我們為了確認真的有使用到Azure Cache Service,所以我們這邊稍微對Cache Service的Configure做一個調整,我們把時間調整成1min;這樣做的意思是表示,這個Cache的生命只有一分鐘的時間( 好可憐… ),當一分鐘過後,這個Cache就會消失了…

image

但我們在MVC的OutputCache是設定120秒阿(兩分鐘),是的,所以如果真的有存到Azure Cache Service的話,雖然MVC的OutputCache是設定兩分鐘,但實際上,到一分鐘的時候,在Azure上的Cache就會消失了,是沒辦法到兩分鐘的;而如果設定失敗…那就會有存活兩分鐘的現象… (通常也會直接報錯了…)

最終執行的結果如下,第一次執行的毫秒是584.

image

過了一分鐘後,變成346…好吧,我想這樣大家也看不出來…總之,如果有興趣的話,大家可以試試看,這部分還滿簡單的喔!

image

這樣就完成了Cache..

後記

其實如果要使用Session也很簡單,只要稍微調整一下,原本打算一併寫的,但畢竟現在已經有中文的資料了,所以只拋磚引玉的寫一篇關於OutputCache的,而未來如果有需要,會再寫一篇關於Session的,那現在如果有很急的朋友們,可以先去參考看看中文的資料喔~~謝謝~~

參考資料

ASP.NET MVC - Mobile上的Safari自動將數字變成Phone Number

$
0
0

其實這是個小小的問題,而且也和ASP.NET MVC無關…主要是在Mobile上的Safari他太聰明!?了,將我們網頁上的數字,自動辨識成Phone Number…如下圖…原本是日期的2013 08 07變成了聯絡資訊…

IMG_0281

當然,原本的HTML是沒甚麼問題的。

<div class="mainBar" id="home">
    <div class="container">
        <div class="row">
            <div class="span12">
                <h1>Study4Love</h1>
                <p><time>2013 08 17</time> 新竹</p>
                <p>
                <a href="http://registrano.com/events/eeb127" class="register" target="_new">已結束</a>
                </p>
            </div>
        </div>
    </div>
</div>

主要原因還是因為Mobile上的Safari雞婆了太貼心了,解決的方法很簡單,只要加上一個metadata就可以了,如下。

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="format-detection" content="telephone=no">
<title>@ViewBag.Title</title>

是的,只要加上<meta name="format-detection" content="telephone=no">就可以了;得到的畫面就和原本的一樣了。

IMG_0282

就這樣。

參考資料

Viewing all 144 articles
Browse latest View live