只有累積,沒有奇蹟

2019年2月27日 星期三

[SQL] Sql Server Management Studio 搜尋神器 - Hunting Dog

前言 
【工欲善其事,必先利其器】相信各位高手中都有私藏的好工具,來協助自己在開發或是除錯時可以更快的達到目的,舉例來說如果是在 Visual Studio IDE 都會建議安裝 Resharper 讓你更快地進行程式碼的重構或是測試,代碼有多語系有建立 Resoure 語系檔時會建議 RegX Resource Manager 快速建立多語系資訊,今天要介紹的是在 SQL Server Management Studio (SSMS) 中常會有需要搜尋 Table、Stored Procedure、View 等相關SQL Object 物件資訊,在之前往往都要按右鍵點選 filter 選項在輸入 key word,在按下搜尋才可完成搜尋的動作,其實可以透過 SQL 搜尋工具 Hunting Dog 在其搜尋介面同時搜尋 sql 物件並將其搜尋結果同時出來,自己在使用上十分滿意也常推薦給需要的朋友使用,今天就來分享 Hunting Dog 在 SSMS 的安裝及基本操作說明。

安裝 Hunting Dog 
下載傳送門 : SQL Hunting Dog 
備註 : 僅支援 SSMS 2008/2012/2014
Step 1 : 點選下載網址,右上角 download
Step 2 : 開啟安裝檔案 HuntingDog-3.5.0.msi > 瘋狂點擊下一步
Step 3 : 按下 Finish,安裝完成

Hunting Dog 功能 
接著開啟 Sql Server Manager Studio就會發現右方有新出現Hunting Dog 搜尋區域視窗
1. Server Name : 可選擇目前已連線的 Server Name 清單
2. Database Name : 選擇 Server 底下的 database 
3. Search input area : 要搜尋的 key word
為了 Demo 方便下載了最有名的北風資料庫做為示範,方便下面介紹快速搜尋與修改功能

快速搜尋
操作及使用方式相當簡單,透過輸入框輸入關鍵 key word,hunting dog 工具就會搜尋相關符合的 Table、SP、Function、View 等物件呈現在下方清單,並可針對 Server Name 、Database 進行快速地切換;說再多都不如實際操作一遍,以下就簡單 Demo 搜尋北風資料庫中 Order、employee 文字分別會如何呈現
透過上圖可以發現,搜尋 Order 時候會同步找 Table 與 SP 相關符合的物件資料,在搜尋上相當方便,不用在左邊區塊進行切換搜尋各自的物件,真正達到快速搜尋的功能。

快速修改
SSMS 內建提供的搜尋功能需要較多的步驟,舉例說要查 SP 名字中有 Order keyword 的物件,操作步驟c會是 : Stored Procedures 按右鍵 > filter > filter settings > 輸入 "Order" > 按下OK > 點擊 Stored Procedures > 顯示搜尋結果;搜尋步驟算是十分的繁瑣;但在 hunting dog 提供快速查詢與修改的功能,
在物件上點選右鍵,即可以針對此物件進行 Select / Edit / Design / Script Table / Locate 等五種功能選項,各功能說明如下
  • Select Data : 產生 Select 該物件的語法,如果是 Table 會執行 TOP 200 查詢結果
  • Edit Data : 顯示選擇物件 body 資訊
  • Design Table : 開啟設計 Table 畫面
  • Script Table : 產生 Table script 語法
  • Locate : 定位到選擇物件位置
已上僅列出常見的功能資訊,更多功能與介紹可以參考官方網站說明 : 傳送門

心得
這套工具從接觸至今真的是十分推薦,一來是因為內建的搜尋有用但是過於繁瑣,假設一天中遇到很多查詢物件的事情時,點選過多步驟就會花費更多的時間;有效的利用工具來節省自己的時間,才可以算是偷時間的一種方式;也可以說把時間節省下來,在把它花在值得花費的地方,才算是有效益的;也謝謝 T 社前同事 N 大的提醒,不然也忘記自己還有這套神器可以分享。

參考
sql-hunting-dog

2019年2月26日 星期二

[.NET] StackExchange.Redis.RedisServerException : 'ERR Error compiling script'

問題 
這幾天在對新專案做 POC,開始對 Redis Server 新增資料做測試,有個 Test Case 在使用 Lua script 新增多筆資料到 Redis Server 時候發生錯誤,錯誤訊息為  "StackExchange.Redis.RedisServerException: 'ERR Error compiling script (new function): user_script:1: function or expression too complex near ''insert script'' ' " ,這篇就針對此案例作簡單紀錄與分享若是有不清楚或是錯誤的地方歡迎討論予糾正

解決方法 
首先先看一下案發現場的 code 如下
private static void InsertBy_LuaScript(IEnumerable<string> input)
{
    var insertValues = String.Join(",", input.Select(o => $"'{o}'"));
    string luaScript = $"redis.call('rpush', 'Luascript', {insertValues})";

    var prepared = LuaScript.Prepare(luaScript);
    RedisConnection.GetDatabase().ScriptEvaluate(prepared);    
} 
針對 function 所傳遞進來的集合做字串相加,最後在將所有相加後的字串當作 redis.call 的參數,舉例輸入集合為 test01、test02、test03,其變數 luaScript 結果 redis.call('rpush','Luascript','test01', 'test02', 'test03') ,最後將此 script 傳入 LuaScript.Prepare API 執行;此語法在測試數量少的時候正常,但後期逐漸地把測試筆數加到 300 筆時,就會產生執行失敗跳出下列錯誤訊息
經 debug 後發現異常時其 lua script 輸出如下
redis.call('rpush', 'Luascript', '0','1','2'...'299')
該 script 當遇到新增筆數量大時,就會變成參數過度擴增的狀況,有可能是因為 redis.call 支援不了這麼多參數,且用此段語法在 lua script online 進行測試也是 compiler error,因此心中判定此種寫法失格出局,改良後的寫法如下
private static void InsertBy_LuaScript(IEnumerable<string> input)
{    
    StringBuilder sb = new StringBuilder();
    foreach (var item in input)
    {
        sb.AppendLine($"redis.call('rpush', 'Luascript', {item})");
    }

    var prepared = LuaScript.Prepare(sb.ToString());
    RedisConnection.GetDatabase().ScriptEvaluate(prepared);
} 
使用 stringBuilder 將輸入集合內容匯總為字串,每筆輸出都單獨定義其 redis.call 其設定值參數,改完後測試筆數可超越原本的限制 300 筆,測試 10000 筆資料也沒問題,宣告結案打完收工 

心得
對於 lua script 不熟悉因此踩到這基本的雷,但轉個念頭想也是因為自己因為對於基本語法不熟悉,才會造成錯誤的使用,也提醒下次遇到類似情況時可以先搞清楚觀念,或許很多雷就不會在踩到

2019年2月24日 星期日

[.NET] 在 Redis 批次新增 List 資料的方案選擇

前言 
專案上遇到有個情境是針對 Redis 的 List 做大量新增的動作,但在新增的同時又希望兼顧效能,因此這篇文章是研究在 StackExchange.Redis 提供的 API 中幾個新增 List 的方式,如何使用以及簡單測試多筆資料時消耗的時間比較,若是有不清楚或是錯誤的地方歡迎討論予糾正

批次新增 List 型別 
由於考量到使用情境是類似 Queue 順序性是重要的,因此是透過 Redis 中的 List 型別做研究與測試,根據 StackExchange.Redis 提供的 API Document 批次新增多筆 List 型別可以使用下列方式
  • ListRightPush
  • CreateBatch
  • Lua Script
  • FireAndForget
以下就分別針對這三種方式做簡單介紹與說明,在介紹之前先說個重要的觀念 連線管理,在與 Redis 的連線會由 ConnectionMultiplexer 類別所管理,盡量避免每個 Request 都重新建立 TCP 連線與釋放,建議共用已經建立好的 Singleton 物件,連線管理主要 sample code 如下
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    string cacheConnection = "127.0.0.1:6379,syncTimeout =3000";
    return ConnectionMultiplexer.Connect(cacheConnection);
});

private static ConnectionMultiplexer RedisConnection => lazyConnection.Value; 

方式一 : ListRightPush
使用迴圈方式逐一的呼叫 ListRightPush 方法將資料新增到 Cache Server 上,缺點是每次請求都需要等待回傳的結果,如果在一次新增大量資料或是網路狀況不穩定時,有可能會發生 Timeout 的狀況
private static void InsertBy_ListRightPush(IEnumerable<string> input)
{
    foreach (var entity in input)
    {
        RedisConnection.GetDatabase().ListRightPush(name, entity);
    }
} 

方式二 : CreateBatch
CreateBatch 是把需要執行的指令打包成一個 script 送出去,接著等待指令執行的結果;使用方式是一開始使用 CreateBatch 指令,最後接 Execute 方法送出
private static void InsertBy_CreateBatch(IEnumerable<string> input)
{
    var batch = RedisConnection.GetDatabase().CreateBatch();
    
    foreach (var entity in input)
    {
        RedisConnection.GetDatabase().ListRightPush(name, entity);
    }
    
    batch.Execute();
} 

方式三 : Lua Script
在 Redis 中也支援 Lua script,Lua script 是一個輕量級內嵌式的程式語言,在 StackExchange.Redis 官網有提供使用 Lua script 語法說明文件 script,應用在此情境可以改為下列範例
private static void InsertBy_LuaScript(IEnumerable<string> input)
{
    var name = MethodBase.GetCurrentMethod().Name;

    StringBuilder sb = new StringBuilder();
    foreach (var item in input)
    {
        sb.AppendLine($"redis.call('rpush', 'Luascript', {item})");
    }
    
    var prepared = LuaScript.Prepare(sb.ToString());
    RedisConnection.GetDatabase().ScriptEvaluate(prepared);
} 
其中可以看到 redis.call 第一個參數為 rpush (List type);第二個參數為對應的 RedisKey;第三個參數為需要新增的資料,以此情境來說新增資料為 000001、000002、000003,因此需要針對輸出集合做轉換,將000001 前後加上 ''變為 '000001',對應到 Lua script 指令則為 rpush 'luascript' '000001','000002','000003' 

方式四 : FireAndForget
第一種的方式是會等待 Redis Server 新增結果,但如果你不想等待回傳結果時,可以設定 flags 為 fireAnd Forget,也就是俗稱的射後不理
private static void InsertBy_FireAndForget(IEnumerable<string> input)
{   
    foreach (var entity in input)
    {
        RedisConnection.GetDatabase().ListRightPush(name, entity, flags: CommandFlags.FireAndForget);
    }    
} 

測試花費時間 
以上針對其四種方式介紹其使用方式,接著想要針對特定筆數花費的時間做比較,在每個新增的 function 加上 stopwatch 時間戳記,來了解各自所花費的時間,透過新增成功後的數據資料作為應用前的評估

前置作業
Server : 在本機環境使用 Docker 架設 Redis Server,版本為5.0.3
Client : 測試專案為 .Net Framework Console App
系統資訊 
  • Windows 10 專業版
  • CPU : i7-8550U @1.8G
  • 記憶體 : 16G
套件 : 使用 StackExchange.Redis,安裝方式請參考 [Redis] C# 存取 Redis - 使用 StackExchange.Redis
測試情境 
  • 資料型態 List : 專案使用情境需求是要用到 Queue,測試資料型態為 List 
  • 新增資料方式 : 使用 StackExchange.Redis 提供的 ListRightPush、CreateBatch、Lua Script 以及 FireAndForget

測試代碼
根據前面提到的加上時間戳記,更新後的 sample code 如下
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using StackExchange.Redis;

namespace Redis
{
    class Program
    {
        private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
        {
            string cacheConnection = "127.0.0.1:6379,syncTimeout =3000";
            return ConnectionMultiplexer.Connect(cacheConnection);
        });

        private static ConnectionMultiplexer RedisConnection => lazyConnection.Value;
        private static Stopwatch sw = new Stopwatch();
        static void Main(string[] args)
        {
            cleaUpData();

            // initial Data ex : 000001, 000002, 000003..etc
            var count = 100;
            var data = new HashSet<string>();
            for (int i = 0; i < count; i++)
            {
                data.Add(i.ToString().PadLeft(6, '0'));
            }

            // use single insert 
            InsertBy_ListRightPush(data);

            // createBatch
            InsertBy_CreateBatch(data);

            // Lua script 
            InsertBy_LuaScript(data);
            
            // use single insert & fireAndForget
            InsertBy_FireAndForget(data);

            Console.ReadKey();
        }

        private static void cleaUpData()
        {
            var RedisDB = RedisConnection.GetDatabase();

            RedisDB.KeyDelete("ListRightPush");
            RedisDB.KeyDelete("FireAndForget");
            RedisDB.KeyDelete("CreateBatch");
            RedisDB.KeyDelete("Luascript");
        }

        private static void InsertBy_LuaScript(IEnumerable<string> input)
        {
            var name = MethodBase.GetCurrentMethod().Name;

            sw.Reset();
            sw.Start();

            StringBuilder sb = new StringBuilder();
            foreach (var item in input)
            {
                sb.AppendLine($"redis.call('rpush', 'Luascript', {item})");
            }
            
            var prepared = LuaScript.Prepare(sb.ToString());
            RedisConnection.GetDatabase().ScriptEvaluate(prepared);

            sw.Stop();
            Console.WriteLine($"{name} total cost : {sw.ElapsedMilliseconds}");
        }

        private static void InsertBy_CreateBatch(IEnumerable<string> input)
        {
            var name = MethodBase.GetCurrentMethod().Name;
            var batch = RedisConnection.GetDatabase().CreateBatch();
            sw.Reset();
            sw.Start();
            foreach (var entity in input)
            {
                RedisConnection.GetDatabase().ListRightPush(name, entity);
            }
            sw.Stop();
            batch.Execute();
            Console.WriteLine($"{name} total cost : {sw.ElapsedMilliseconds}");
        }

        private static void InsertBy_FireAndForget(IEnumerable<string> input)
        {
            var name = MethodBase.GetCurrentMethod().Name;
            sw.Reset();
            sw.Start();
            foreach (var entity in input)
            {
                RedisConnection.GetDatabase().ListRightPush(name, entity, flags: CommandFlags.FireAndForget);
            }
            sw.Stop();
            Console.WriteLine($"{name} total cost : {sw.ElapsedMilliseconds}");
        }

        private static void InsertBy_ListRightPush(IEnumerable<string> input)
        {
            var name = MethodBase.GetCurrentMethod().Name;
            sw.Reset();
            sw.Start();
            foreach (var entity in input)
            {
                RedisConnection.GetDatabase().ListRightPush(name, entity);
            }
            sw.Stop();
            Console.WriteLine($"{name} total cost : {sw.ElapsedMilliseconds}");
        }
    }
}

數據結果
method500100010000
ListRightPush4039916665
CreateBatch4476986701
Lua Script3831143
FireandForget912201
使用 Redis Desktop Manager 來確認資料,確認後寫入成功


心得
這篇介紹幾種新增 List 的方式與其簡單測試數據資料,排除掉射後不理來看(因為根本不會知道成功或失敗),用 Lua script 新增大量資料的回應時間都是最快的,其次是 createBatch 方式,可以提供需要使用的人數據與思考方向,原本想測試更多筆數的數據,但由於近期筆電不知原因每小時都會聽到風扇的哀號聲,有時覺得像是飛機要起飛了一樣,對於測試來說是一大挑戰,或許等到筆電康復之後再進行更大筆數據的測試,之後如果有新數據會在分享出來

參考
StackExchange.Redis

2019年2月22日 星期五

[Docker] Error response from daemon: Conflict. The container name "ooo" is already in use by container "xxx"

問題 
最近自己在嘗試 Docker 的一些應用,起 container 時會執行 Docker run ,但今天跳出異常錯誤訊息為
Error response from daemon: Conflict. The container name "ooo" is already in use by container "xxx". You have to remove (or rename) that container to be able to reuse that name."  或許是初老症狀病情變嚴重或是忘記吃銀杏,這問題第二次遇到自己還想不起來該怎麼解,為了紀念自己的愚蠢,特此記錄遇到這問題該怎麼處理,避免自己下次再遇到又忘記可以直接查看自己的筆記就好。 

解決方式
在執行 Docker run image 時候會透過 --name 指定 container 的名字,這錯誤訊息是告知你要執行的 container Name 已經重複,麻煩請移除掉或是重新命名

查詢目前 container
首先,先查詢目前正在執行中的 container 有哪些容器,執行以下指令
docker ps -l

移除命名重複 container
發現正在執行的 container 有相同名字的容器,因此執行下列指令把名字重複的移除掉
docker kill ba94
docker rm ba94
為確保有正常移除再重新執行查看目前容器狀態 
docker ps -l

重新執行
重新跑一次剛剛異常的指令 
docker run --name redis-lab2 -p 6379:6379 -d redis
輕鬆解決, 自己一直忘記實在是太愚蠢了阿阿阿阿

完整記錄 
PS D:\> docker run --name redis-lab2 -p 6379:6379 -d redis
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: Conflict. The container name "/redis-lab2" is already in use by container "ba94e55f88fe317a0a20138eb889c3f9b8b7eee67538834ab5a58938b57e74cf". You have to remove (or rename) that container to be able to reuse that name.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
PS D:\> docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
ba94e55f88fe        redis               "docker-entrypoint.s…"   6 hours ago         Up 6 hours          0.0.0.0:6379->6379/tcp   redis-lab2
PS D:\> docker kill ba94
ba94
PS D:\> docker rm ba94
ba94
PS D:\> docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                    NAMES
e819ea3d7a7b        redis               "docker-entrypoint.s…"   7 days ago          Exited (255) 3 days ago   0.0.0.0:6379->6379/tcp   redis-lab
PS D:\> docker run --name redis-lab2 -p 6379:6379 -d redis
3dff87ea2212c6489aae3459b2f5428da0b57446d75b5f68b22a8984632f839f
PS D:\>

參考
Docker Engine command line reference 

2019年2月20日 星期三

[VisualStudio].NET 程式碼品質分析利器 SonarLint

前言 
前陣子部門導入 SonarQube 來分析程式碼品質的工具,會定期掃描當前 GIT 上前後端程式碼分析其代碼質量、Code Smell、找到可能潛在的問題、安全漏洞、單元測試涵蓋率,並可透過視覺化 Dashboard 介面查看目前分析代碼的狀態,且支援分析 25 種以上程式語言,可以說是整合性相當高的程式碼分析工具。今天與同事討論提到 SonarQube 有出擴充工具 SonarLint 與 Visual Studio IDE 做整合,可以在開發時即時做程式碼分析與弱點掃描,不用等到 Commit 後在進行分析,SonarLint 圖片 LOGO 設計十分有趣右下角是紅色波浪提示訊息,今天就來分享 SonarLint 在 Visual Studio 2017 的安裝及基本操作說明。

安裝 SonarLint 
Step 1 : 選擇 Tools > Extension and Updates
Step 2 : 搜尋 sonarlint > 點擊 SonarLint for Visual Studio 2017 > 安裝
Step 3 : 會跳出下載視窗下載檔案,接著關閉 Visual Studio IDE 才會開始執行安裝程式
Step 4 : 會執行 SonarLint for VS 2017 安裝檔案,瘋狂按下一部結束這回合
Step 5 : 安裝完畢之後,重新啟動 Visual Studio > Tools > Extension and Updates 
發現 SonarLint for Viaual Studio 已安裝完成

SonarSource 分析程式碼 
在安裝完畢之後,我們開始簡單寫一段代碼測試看 SonalSource 是否會提示
private void MethodTest2(int param)
{
    if (param != null)
    {
        // todo
    }
}
以上述 Sample Code 為例,在安裝完 SonarLint 之後會提示這段 Code 程式碼有問題,將滑鼠移至綠色提示線上會顯示 param != null 這段代碼會永遠成立,因此會判斷會永遠為 true,
另外在下方 Error List 視窗,也會一併提醒分析整個專案後發現可能的問題清單,讓開發者可以清楚地了解異常的原因與發生時機

Sonarsource Rules
透過上述簡單的範例,可以知道 sonalLint 工具是即時的掃描與分析靜態程式碼,在掃描靜態程式碼時是根據甚麼 Rule 來定義正常或異常呢 ? 在 SonarQube 有提供一份規則清單(Sonarsource rules),其中涵蓋了支援程式語言的程式碼品質相關 Rule,主要分為三大項 Code Smells、Bugs、Vulnerability,以 C# 為例截至目前為止支援的 rules (或者可以說建議項目) 有 373 種,其中都有詳細的 
(1) 項目名稱 
(2) 項目詳細說明搭配 Sample code 範例讓你更容易了解原因
更多詳細的內容可以參考 sonarsource rules 

簡單比較 Before&After
或許到這邊還沒有感覺,接下來在 Sonarsource Rules 中隨便找出兩項 Rule 並簡單比較其畫面的差異,可以更有感覺知道安裝後的差異,以下面兩者安裝 sonarLint 套件之後的 sample code 為例,如果發現有更好程式碼寫法時,會有提示告知(個人覺得很明顯 XD),滑鼠移上去也會有提示說明建議的原因,相當實用。

提示 : try catch 沒寫 catch 處理
Generic exceptions should not be ignored

提示 : if 判斷重複時
手誤輸入兩個if 判斷重複

心得
工欲善其事,必先利其器;在過去幫團隊 Code Review 時往往都是透過人工的方式進行,但只要有人就會有江湖遺漏的可能發生,但如果透過工具來輔助可以更有效率,針對有爭議的項目看說明與 sample code 做討論,更有效的達到團隊的共識與提供程式碼的品質,甚至掃到潛在的安全性議題,針對問題盡早發現並排除,才會是比較有效的方式

參考
sonarlint

2019年2月19日 星期二

[Redis] C# 存取 Redis - 使用 StackExchange.Redis

前言 
前面幾篇在介紹 Redis 的安裝以及使用 Redis Desktop Manager 工具,現在終於回到主題如何用 C# 存取 Redis 服務,在官方網站推薦的 .NET Redis client(s) 有很多種,討論度最高的為 StackExchange.Redis 其開發者在 StackExchange 公司工作且 Library 廣為 .NET 開發者推薦,這篇文章要介紹 StackExchange.Redis 的安裝及基本用法,若是有不清楚或是錯誤的地方歡迎討論予糾正 

安裝 StackExchange.Redis 
Step 1 : 開 Nuget packer Manager 輸入 StackExchange.Redis,目前提供版本為 2.0.519 版,點擊下載
Step 2 : 安裝時會提示下載套件相依的 dll 內容,選擇下一步即可
或者直接在 Nuget console 直接輸入下列指令進行安裝
PM> Install-Package StackExchange.Redis 
確認下載成功 : 在 dll 中看到有即下載成功

StackExchange.Redis 基本用法 
建立連線
在存取前,首先第一步需要的就是與 Redis 建立連線的動作,在建立連線前想先提到 ConnectionMultiplexer 類別,ConnectionMultiplexer 是整個 StackExchange.Redis 核心類別,Multiplex 設計概念可以參考 Jed 大文章有更詳細說明,主要重點是 connection 分享與重用 (shared and reused),因此不需要重複建立 ConnectionMultiplexer 實體物件。
建立連線可以使用 ConnectionMultiplexer.Connect 或是透過 ConfigurationOptions 類別自行定義,以下面例子來說透過兩種建立連線方法皆可
// connectionString
var conn = ConnectionMultiplexer.Connect("127.0.0.1:6379");

// ConfigurationOptions
ConfigurationOptions config = ConfigurationOptions.Parse("127.0.0.1:6379,allowAdmin=true");
var conn2 = ConnectionMultiplexer.Connect(config.ToString()); 
另外,在連線管理上需要注意的是建立連線後重複使用問題,當每發送一個新的 Request 都建立連線,當 Request 量大時頻繁的 Create / Dipose 會影響其效能,解法是透過 Singleton Pattern 包成一個 Helper 類別處理,在 C# 4.0 之後可以透過 Lazy 語法達到此目的,範例如下
public class RedisConnectorHelper  
{                  
    static RedisConnectorHelper()  
    {  
        RedisConnectorHelper._connection = new Lazy<ConnectionMultiplexer>(() =>  
        {  
            return ConnectionMultiplexer.Connect("localhost");  
        });  
    }  
      
    private static Lazy<ConnectionMultiplexer> _connection ;          
  
    public static ConnectionMultiplexer Connection  
    {  
        get  
        {  
            return _connection.Value;  
        }  
    }  
}   

存取 Redis
完成建立連線之後,使用 Redis database 相當簡單,只需透過一行指令即可完成
var db = conn.GetDatabase();
如果在有多台 Redis Server 或是需要使用非同步 API 需求時,我們可以透過 GetDataBase 參數指定 ServerID (databaseNumber)、設定是否為非同步模式(asyncState),databaseNumber 預設為 -1 與 asyncState 預設為 null ;另外在 GetDataBase 方法回傳 IDataBase  interface,在 IDataBase 介面中定義了存取 Redis Server 常用的存取支援的 DataType 方法簽章,舉例來說常見的 String、List、Hash...等,在前面幾篇使用 Redis-cli  command line 設定 String 可以改為以下 Code
// Set
string value = "Hello World";
db.StringSet("Test", value);
// set timeout 5min
db.StringSet("Test", value, TimeSpan.FromSeconds(300));

// Get 
var test = db.StringGet("Test");
簡單完成 GET / SET String,其中還可以指定特定 Key 的過期時間,使用上相當容易上手;

確認資料
存取完要來確認資料是否有正常寫入可以透過 Redis Desktop Manager 管理工具來確認 Redis 資料狀態
正常寫入,打完收工!!!

心得
這篇介紹了如何在 Visual Studio 安裝 StackExchange.Redis 以及基本的應用 StringGet / StringSet 寫法,個人覺得都算是基本的入門之一,就像是一段 Code 會跑跟怎樣寫得好是不一樣的兩件事,在實作上還是有很多細節與眉角需要關注的地方,之後如果有遇到會在分享出來

參考
Redis系列 - C#存取Redis (上)
StackExchange.Redis

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com