Use Memcached in .NET application with Linq

First of all, get the memcached, I user win32 version. http://jehiah.cz/projects/memcached-win32/ version 1.2.1
Secondly, get a client for memcached, I use this one http://memcachedproviders.codeplex.com/ version 1.2
Get the document for the client too, I start without it and I think you should read it in advance.
I will share some of my experience too.

The official documentation is a bit poor, I am going to give an introduction on the main points.

1. Memcached is a universal distributed cache.

i.e. it can run multiple instances and appears to the programmer as one cache server which is programming language independent. A really large hashtable.

2. It stores no object, you’ll have to serialze every object that you want to cache.

3. It won’t throw any exception no matter what happens.

I will focus on how to use the memcached server, not how to setup since you should be run it without a problem.

Setup the client in your application. Unarchive and add reference to all three .dll in your project.

Then configure your web.config or app.config like this, inside <configSections> tag, add the following:

<section name="cacheProvider" type="MemcachedProviders.Cache.CacheProviderSection, MemcachedProviders"
 allowDefinition="MachineToApplication" restartOnExternalChanges="true"/>
 <sectionGroup name="enyim.com">
 <section name="memcached"
 type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
 </sectionGroup>
 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>

This tells the application that there will be a section with tag <cacheprovider> and <log4net>. Also will have a section with tag <enyim.com> who has a child tag <memcached> inside. You can just copy and paste the above, it should work.

Then add the detail settings in <configuration> tag.

<cacheProvider defaultProvider="MemcachedCacheProvider">
 <providers>
 <add name="MemcachedCacheProvider" type="MemcachedProviders.Cache.MemcachedCacheProvider, MemcachedProviders"
 keySuffix="_MySuffix_" defaultExpireTime="2000"/>
 </providers>
 </cacheProvider>

 <enyim.com>
 <memcached>
 <servers>
 <add address="192.168.1.2" port="11211" />
 </servers>
 <socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" />
 </memcached>
 </enyim.com>

 <log4net>
 <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}]- %message%newline" />
 </layout>
 </appender>
 <root>
 <priority value="WARN"/>
 <appender-ref ref="ConsoleAppender">
 <filter type="log4net.Filter.LevelRangeFilter">
 <levelMin value="WARN"/>
 <levelMax value="FATAL"/>
 </filter>
 </appender-ref>
 </root>
 </log4net>

You can change the default expire time. Server address is the host which you run memcached and 11211 is the default port.

Caching string and serialized object should be something you already know. For simple class, just add [Serializable] to the class.

Let’s see how it works with LINQ.

To serialize LINQ object, open .dbml design view, select serialize mode to unidirectional.

Then you will need to use DataContractSerializer to actually serialize your object. For more information.

There are a few serializer, XML, binary, JSON, etc. I am using DataContractJsonSerializer since it should be faster than XML. The following code snippet serialize and cache the object array to memcached.

//create a serialize provider with specify object type
DataContractJsonSerializer serializeProvider = new DataContractJsonSerializer(typeof(myClass[]));
//a memory stream as buffer since the provider do not directly generate string
 using (MemoryStream ms = new MemoryStream())
 {
 serializeProvider.WriteObject(ms, myClassArrayObject);
 byte[] l_buffer = new byte[ms.Length];
 ms.Position = 0;
//If the string is out of integer range, skip it, you can do whatever you need to handle this
 if (ms.Length < int.MaxValue)
 {
 ms.Read(l_buffer, 0, (int)ms.Length);
 string l_serialized = Encoding.Unicode.GetString(l_buffer);
//remove existing cache with the same key
 DistCache.Remove("keyString");
 DistCache.Add("keyString", l_serialized);
 }
 else
 {
 throw new Exception("object data large.");
 }
 }

Then you can check whether you succussfully cache it with telnet.

Telnet to your server and type the command ‘stats’, it will then shows the status of your memcached.

curr_items is the number of items inside memcached.

There is some common practices in choosing the hash key but that is another topic.

I am using Application:Method:Parameters:Salt and then hash it with SHA256, convert it to base64.

This should be enough for testing purpose, you can come up with your own hash decision.

Then we will get the cache and deserialize it to our object.

string l_serialized = (string)DistCache.Get("keyString");
 DataContractJsonSerializer serializeProvider = new DataContractJsonSerializer(typeof(myClass[]));
 using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(l_serialized)))
 {
 myClass[] members = (myClass[])serializeProvider.ReadObject(ms);
 }

You can do this with your object, object array, object collection, etc.

But remember you are in a different data context if you get you data from cache.

This will need some workaround to update or delete data with Linq.

I will cover this part later in another article.

中文版

Branch in Visual sourcesafe

Amount all those version control system, visual source safe is not the best one for sure.
And maybe the worst…but company policy, so…
No matter what you are developing, branching will come to your face one day.
It is not that straight forward for roll-back and branching in VSS.

In the Visual SourceSafe Explorer, right-click on the project that you want to branch. Then Select Show History.
In the Project History dialog box, select the recursive option if all subprojects and their files are wanted. Click OK.
Select the version you want to branch, and click the Share button. Select the branch after share on the lower left.
Select the project in which you want to create the new branch. Click OK.
In the Share dialog box, type the name you want to give to the new branch and
check the recursive checkbox if you want to branch subprojects. Click OK.

JIRA with Sql Server 2008 Express

You can get detail on how to connect JIRA to SQL Server in Atlassian document
But there is one thing they didn’t mention, or maybe I just miss it.
If you want to connect to Sql Server Expression Edition. The connection string is different.
It should be like :
url=”jdbc:jtds:sqlserver://localhost:1433/jiradb;user=jirauser;password=jirauser;instance=sqlexpress”

ReportViewer DataSource and Expression Walkthrough

There is a problem to many report framework except JasperReport. The field expression syntax and their ability.
ReportViewer is not exception.
I have a post about some basic on using ReportViewer. But I recently found that a little part about binding data source is missing. That is the reason why this post is writen.
The post before is about object data source in code behind. There is one thing I forgot myself too. If you are wordering why your method do not appear in the data source window. A method that returns DataTable can not be a data source. You have to stick to Enumerable data. And in the code behind, you have to go to design view first, see what name of the data source should be named. You will need that to assign the data source to the ReportViewer.
除了JasperReport以外,很多報表工具都有同樣的問題.它們報表內的欄位所使用的語法雜亂及其功能限制.連ReportViewer也不例外.
我之前有一篇關於ReportViewer的基本應用. 但我最近發現中間有一小段關於連結資料源的地方漏掉了.這就是為甚麼我要寫這一篇的原因.
前一篇提到怎樣在code behind連結物件資料源.有一件事我自己也忘記了.如果你搞不懂為甚麼你的資料源取得方法沒有出現在資料源窗格.因為一個回傳DataTable的方法並不能作為一個資料源.你非得要用可列舉資料才行.至於code behind,你應該先去設計檢視,看一下資料源設定了甚麼名稱.在你指定資料源時要用到.
After data source are bound. You may want to do some extra checking in your expressions. Like show only positive number.
According to ReportViewer, it tells you that the expression is in VB syntax, I doublt it. You can’t even use If Then Else.
Here is the Link of MSDN on expression syntax.
If you want to check if a number is NaA, you can’t… The double in RDLC don’t have NaN property.
I just check it if it is larger than zero since I am removing negative number anyway.
在資料連結後.你可能會想給你的內容表達式加一點檢查.例如只顯示正數.根據ReportViewer的說明,它說所使用的是VB語法,我很懷疑.你連If Then Else都不能用.這是MSDN有關於表達式語法的文章.如果你想檢查一個數字是否NaN,沒辦法…因為RDLC裡的double並沒有NaN這個屬性.我只是檢查數值是否大於零,反正我都要忽略負數.
The syntax should be like
語法如下

Iif(ExpressionOfField > 0, ExpressionOfField, "")

There is also an issue when you are using ReportViewer on IIS 7. You may encounter JavaScript error and your image buttons turn into ‘X’. That is because the HttpHandler registration is moved from System.Web to System.WebServer.
如果你在IIS 7上運行你的ReportViewer. 你可能會遇到JavaScript錯誤並發現你的小圖示都變成一個’X’.那是因為HttpHandler的註冊從System.Web移到System.WebServer了.
You can solve it by.
解決方法如下.

Open Internet Information Services (IIS) Manager and select your Web application.
打開IIS管理員,選擇你的網路應用程式
Under IIS area, double-click on Handler Mappings icon.
在IIS區,點兩下處理常式對應.
At the Action pane on your right, click on Add Managed Handler.
在右邊的動作區,點新增事件處理常式
At the Add Managed Handler dialog, enter the following:
在新增管理對話框,輸入以下
Request path: Reserved.ReportViewerWebControl.axd
Type: Microsoft.Reporting.WebForms.HttpHandler
Name: Reserved-ReportViewerWebControl-axd
Click OK.
按確定

The solution was found here, thanks to Antonio Ooi. I hope he don’t mind me quoting his article.
解決方法來自這裡,感謝Antonio Ooi.希望他不介意我引述其文章.

How To Turn Up JIRA service debug Level

It is actually adding JAVA options for starting JVM, just like what you did starting some application server.
From Control Panel > Administrative Tools > Services, open up JIRA service property form.
Note the service name then run this command in command line (console)
%JIRA%> tomcat5w //ES//%SERVICENAME%
Go to Java tab page, add your option to Java Options.
For example, -Dmail.debug=true
Save and restart.

Setup JIRA standalone 3.13.3 with Gmail SMTP

Gmail use the port 465/587 and STARTTLS for its SMTP. This gets many application have trouble using Gmail SMTP to send mail. That is from what I observe.
Recently I recommand JIRA to my boss and he agree to give it a go. I am sure good and commercial product like JIRA must be able to
support Gmail SMTP. But that is still not a easy setting as normal SMTP.
Gmail使用連接埠465/587加上STARTTLS作為它的SMTP通訊.這讓很多網頁應用程式要用Gmail的SMTP發送郵件時遇上困難.至少我遇到不少這樣的例子.
最近我建議我上司使用JIRA而他同意試用看看.我很肯定像JIRA這種良好的商業產品一定可以跟Gmail的SMTP溝通.只是跟一般SMTP的設定比較還是不太簡單.

I first try to setup by reading their document about SSL SMTP, which is this one. WARNING, This procedure won’t work.
And then of course I turn to their support since I brought their product. Their live chat service is quite good. Here is how I successfully connect my JIRA with Gmail. I am writing this down because if you want to make it work, you will need information from different parts of different document. And those document are not easy to understand if you have little experience on TOMCAT and JAVA. I am going to write this in a way that average technical person could understand.

我首先邊讀他們關於SSL SMTP的使用文件邊設定.就是這篇.警告,這篇的方法不可行.
然後因為我買他們的產品,我當然是去找他們的支援.他們的即時對話服務還不錯.下面就是我成功連接我的JIRA和Gmail的方法.我把他寫下來因為如果你也想像我那樣設定,你需要很多來自不同文件的資訊.而這些文件如果你沒有使用過TOMCAT和JAVA就會不是那麼容易看得懂.我會用一般技術人員都看得懂的方式去寫下來.

You will need to have SSL support, I use OPENSSL, an open source SSL and TLS protocol implementation. REMARK, this may not be necessary since I later found out that we are connection Gmail SMTP with JNDI but not SSL. After you install OpenSSL, use command line (console), go to %OPENSSL%\bin. run this command to get Gmail smtp public key.
你需要能支援SSL,我用的是OPENSSL,一個開源的SSL和TLS協定實作.注意,這可能並不是必需的,因為我後來發現我們並不是用SSL而是用JNDI去跟Gmail的SMTP溝通.在你安裝OpenSSL後,運行命令提示字元(M$的翻譯還真爛…),然後到%OPENSSL%\bin.運行這個命令去取得Gmail smtp的公用金鑰.

cmd>openssl s_client -connect smtp.gmail.com:465 > c:\key.txt

Then open the text file and copy the public key. Like the following
然後打開那個文字檔並複制那個公用金鑰.像下面的

-----BEGIN CERTIFICATE-----
MIICiTCCAfKgAwIBAgIBADANBgkqhkiG9w0BAQQFADB/MQswCQYDVQQGEwJBVTEM
MAoGA1UECBMDTlNXMQ8wDQYDVQQHEwZTeWRuZXkxEjAQBgNVBAoTCUF0bGFzc2lh
bjEaMBgGA1UEAxMRY3ZzLmF0bGFzc2lhbi5jb20xITAfBgkqhkiG9w0BCQEWEmlu
Zm9AYXRsYXNzaWFuLmNvbTAeFw0wNTA5MjMwNjUyNTNaFw0wNjA5MjMwNjUyNTNa
MH8xCzAJBgNVBAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTES
MBAGA1UEChMJQXRsYXNzaWFuMRowGAYDVQQDExFjdnMuYXRsYXNzaWFuLmNvbTEh
MB8GCSqGSIb3DQEJARYSaW5mb0BhdGxhc3NpYW4uY29tMIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDhwAgx/gDgKe9tBjUCj7JtVkwQSzj2Dq0PHiJu1AWUYWFW
ivbBWaWSYbt/w9vIRSL8OlGVOLnlFOH5o7QIpIBZvd3xBMv6DxMijM86/hu8QTPt
KcMuqBTGpu1T846SzNncj883wSE1hXxezCgEFCsqyC7dVX4l0Ay6zgzkt2wc3QID
AQABoxUwEzARBglghkgBhvhCAQEEBAMCBkAwDQYJKoZIhvcNAQEEBQADgYEAJOgg
O4brCcQa3IgONo8UmLcHo6Rq+Py6ZA3ueUegy/uyQ358JUeL4kktXuYL9gAPCuMc
hsC1iyaOrWY/S9S67w2ZWqc+uYX9ophFHkxK1r3YiaiMpEzMyB12VWSrOITcR0LV
7NTWfxfPLUpkDbj+Mw/66QJkI0lqBvcKn3KXI74=
-----END CERTIFICATE-----

Create a text file C:\certs\imapd.pem, paste the key into it.
建立一個文字檔C:\certs\imapd.pem,把金鑰貼在裡面.
We now add the key into Java keystore by running the following command at %JAVA_HOME%\
接下來把金鑰加到Java的keystore裡.在%JAVA_HOME%\裡執行下面的命令

bin\keytool -import -file c:\certs\imapd.pem -alias smtp.gmail.com -keystore lib\security\cacerts

Do not go inside bin folder. This command will add the key to java default keystore.
Then we setup our TOMCAT like this. Modify %JIRA%\conf\server.xml
不要進到bin資料夾. 這命令會把金鑰加到java預設的keystore裡.
然後我們設定我們的TOMCAT如下.修改%JIRA%\conf\server.xml

<Context path="" docBase="${catalina.home}/atlassian-jira" reloadable="false">
 ....
<Resource name="mail/GmailSmtpServer"
 auth="Container"
 type="javax.mail.Session"
 mail.smtp.host="smtp.gmail.com"
 mail.smtp.port="465"
 mail.smtp.auth="true"
 mail.smtp.user="myusername@gmail.com"
 password="mypassword"
 mail.smtp.starttls.enable="true"
 mail.smtp.socketFactory.class="javax.net.ssl.SSLSocketFactory"
 />
 </Context>

If you don’t have this resource block, just add a new one. Replace user and password with your own account.
Next, Cut %JIRA%\atlassian-jira\WEB-INF\lib\javamail-1.3.2.jar and %JIRA%\atlassian-jira\WEB-INF\lib\activation-1.0.2.jar And paste the files into %JIRA%\common\lib.
如果你沒有這資源,就加一個新的.把使用者和密碼改成你自己的帳號.
下一步, 剪下%JIRA%\atlassian-jira\WEB-INF\lib\javamail-1.3.2.jar和%JIRA%\atlassian-jira\WEB-INF\lib\activation-1.0.2.jar 並貼上到%JIRA%\common\lib.

And then restart JIRA and perform the last step.
重新啟動你的JIRA並進行最後一步
Set up your mail server in JIRA: Administrator > Global Settings > Mail Servers
設定你的JIRA郵件服務器: 管理者介面->全域設定->郵件伺服器
Name your file: Name it whatever you would like.(隨意)
Set your from address: Name it whatever you would like.(隨意)
Set your email prefix: Name it whatever you would like.(隨意)
Leave server name, user name and password blank.
把伺服器名,使用者名稱和密碼留空白
SMTP Port: 25
JNDI Location: java:comp/env/mail/GmailSmtpServer
(Replace GmailSmtpServer with whatever you set your Resource name=”mail/GmailSmtpServer”)
(GmailSmtpServer代入任何之先前設定的資料名稱 name=”mail/GmailSmtpServer”)
You are now ready to use Gmail SMTP.
你已經準備好用Gmail SMTP.
reference: HERE.

Auto increment column int MS SQL Server

I sometimes want to do this to create a field with auto-increment value to use as a sorting index. It is easy to achieve with MYSQL, I am going to show you how to achieve it with MS SQL 2008

Go to design view of your table, select the column which you want it to auto-increment. There will be a ‘Column Properties’ in the lower half of the designer. If you use Right-Click on the table and view its properties, there you can’t do any modification, which is strange to me. Anyway, go find ‘Identity Specification’ in ‘Column Properties’ located at the lower half of the designer.
Choose ‘Yes’ to (is identity)
Set ‘Identity Increment’ to some number, I usually use 1
Set ‘Identity Seed’ to some number, I usually use 1 too.
Save it, Then this column will generate auto-increment value when you insert new record to this table.

This is another very common things that people wants to do, IMHO.
enjoy it and cheers.