Thứ Năm, 20 tháng 12, 2012

Tìm danh sách các Store Procedure,View có liên quan đến Table nào đó trong MS SQL Server

Hôm nay mình cấu trúc lại database nên cần chỉnh sửa 1 số tên cột, xóa 1 số bảng không còn dùng nữa ra khỏi database.

Một điều khá mệt là hệ thống mình kết nối dữ liệu tới database đều sử dụng Store Proc hết, số lượng store proc rất nhiều. Khi sửa tên cột trong table, các store proc nào có gọi đến tên cột của table nó không tự động đổi cho nên khi gọi store proc này sẽ báo lỗi. Thêm 1 điều nữa là khi quyết định xóa 1 table mình phải chắc chắn không có store proc hay view nào đang dùng tới nó.

Sử dụng đoạn lệnh sau để tìm các store proc, view có sử dụng table muốn sửa hay muốn xóa:
  1. use [Database Name]  
  2. SELECT DISTINCT o.name, o.xtype  
  3. FROM syscomments c  
  4. INNER JOIN sysobjects o ON c.id=o.id  
  5. WHERE c.TEXT LIKE '%tableName%'      
Hoặc
SELECT o.name, o.xtype, m.definition
FROM sys.sql_modules  m  
INNER JOIN sysobjects o ON m.object_id = o.id 
WHERE m.definition LIKE '%tableName%' 
Cách làm này có thể không chính xác tuyệt đối (tìm trong nội dung có chứa tên của table) nhưng cũng khá hiệu quả.

Thứ Hai, 10 tháng 12, 2012

Xóa các thẻ Html ra khỏi 1 chuỗi (lấy InnerText của 1 thẻ Html)

Khi có 1 object HtmlElement (System.Windows.Forms) hay HtmlNode (HtmlAgilityPack) thì việc lấy InnerText của nó khá đơn giản, chỉ cần .InnerText là ra.

Trường hợp có 1 thẻ Html nhưng ở dạng chuỗi thì sử dụng regular expression để replace những đoạn có cấu trúc là 1 tag mở hay tag đóng của 1 thẻ Html.

Có rất nhiều mẫu để tìm tag html ví dụ "<[^>]*>" hoặc "<.*?>" . Trường hợp này mình dùng mẫu  "<[^>]*>":
  1. public static string RemoveHtml(this string text)  
  2. {  
  3.     return Regex.Replace(text, "<[^>]*>"string.Empty);  
  4. }  
Test:
  1. string link = "<a href=\"http://www.hanhtranglaptrinh.com/2012/11/goi-ham-javascript-bang-webbrowser.html\">Gọi hàm Javascript bằng webbrowser control C#</a>";  
  2. string anchorText = link.RemoveHtml();//Gọi hàm Javascript bằng webbrowser control C#  

Thứ Ba, 27 tháng 11, 2012

Gọi hàm Javascript bằng webbrowser control C#

Hum nay ngồi làm cái chương trình quét dữ liệu tự động sử dụng webbrowser control.

Do dữ liệu nhiều lên website nó phân trang, sau khi lấy hết dữ liệu của trang hiện tại mình phải tìm đúng cái link để qua trang kế và tự động click vào hoặc lấy url của nó để chuyển đến trang kế.

Ngồi Inspect Element ai ngờ nó sử dụng javascript để qua trang kế ^^. Thay vì phải tìm link này để click vào thì mình dùng webbrowser control gọi trực tiếp hàm javascript này.


Sử dụng webbrowser control để gọi javascript qua trang kế:
  1. private void GoToPage(int page)  
  2. {  
  3.     webBrowser.Document.InvokeScript("gotoPage"new object[] { page });  
  4. }  
Cách làm này đỡ mất công phải tìm đúng thẻ để gọi phương thức click, có thể tăng tự động page thêm 1 sau mỗi trang hoặc nhảy đến 1 trang bất kỳ tùy thích để lấy dữ liệu ^^!.

Xem thêm Điền dữ liệu và tự động click vào button trên website sử dụng webbrowser control c#

Thứ Hai, 19 tháng 11, 2012

Cấu hình thông báo lỗi 404 Directory not found (Không tìm thấy thư mục) cho website trên IIS

Cấu hình thông báo lỗi cho website là điều cần thiết. Trong nhiều trường hợp sẽ che dấu đi lỗi code, version của IIS, .Net Framework,... tránh trường hợp tò mò của những kẻ xấu hoặc hacker lợi dụng các lỗi code hoặc điểm yếu của phiên bản server để khai thác lỗ hổng và phá hoại.

Mình đã có 1 bài viết về cấu hình thông báo lỗi cho website khi truy cập vào 1 file hoặc thư mục không tồn tại trong website.

Tuy nhiên khi mình đưa website lên host (Đã thử trên cả IIS 6 và IIS 7) nó chỉ có tác dụng đối với file .aspx không tồn tại, còn đối với trường hợp người dùng truy cập vào 1 số kiểu file khác hoặc một thư mục không tồn tại thì vẫn bị báo lỗi. Cách khắc phục là cần cấu hình thêm.

Cách 1: Cấu hình trên IIS 7

Trên IIS 6 thì tương tự:

Cách 2: Cấu hình trong web.config IIS7 <system.webServer> </system.webServer>:
(Khi cấu hình trên IIS7 sau đó mở web.config lên sẽ tìm thấy đoạn này)
  1. <httpErrors>  
  2.   <remove statusCode="404" subStatusCode="-1" />  
  3.   <error statusCode="404" prefixLanguageFilePath="" path="http://hanhtranglaptrinh.com" responseMode="Redirect" />  
  4. </httpErrors>  
Chú ý:
Khi test phải publish website lên IIS hoặc hosting. Trường hợp chạy website bằng server ảo do Visual Studio dựng lên kết quả sẽ không chính xác.

Chủ Nhật, 18 tháng 11, 2012

Lấy thông tin dung lượng phân vùng ổ cứng của máy tính bằng C#

Mình có viết 1 cái tool nho nhỏ để check dung lượng ổ cứng của server, mỗi khi dung lượng trống xuống dưới một mức nào đó thì báo động (email,sms ) cho người quản lý vào kiểm tra. Dưới đây là hướng dẫn và demo đơn giản về cách làm:

Add using System.Runtime.InteropServices; và sử dụng DLL Import:
  1. [DllImport("kernel32.dll", EntryPoint = "GetDiskFreeSpaceExA")]  
  2. private static extern long GetDiskFreeSpaceEx(  
  3. string lpDirectoryName, out long lpFreeBytesAvailableToCaller,  
  4. out long lpTotalNumberOfBytes, out long lpTotalNumberOfFreeBytes);  
Sử dụng:
  1. long result, total, free, available;  
  2. result = GetDiskFreeSpaceEx("d:"out available, out total, out free);  
  3.   
  4. if (result != 0)  
  5. {  
  6.     long totalGB = total / (1024 * 1024 * 1024);  
  7.     long freeGB = free / (1024 * 1024 * 1024);  
  8.     long availableGB = available / (1024 * 1024 * 1024);  
  9.     string mess = "Tổng số GB: " + totalGB + "\n";  
  10.     mess += "Tổng số GB trống: " + freeGB + "\n";  
  11.     mess += "Tổng số GB trống xài được: " + availableGB;  
  12.     MessageBox.Show(mess);  
  13. }  
Vì kết quả trả về với đơn bị là byte nên mình chuyển qua GB.

Demo:
Sự kiện Form Load khai báo như sau ( dưới đây lấy thông tin của phân vùng D):

Kết quả:

Dưới đây là thông tin Hard Disk Drives máy mình tại thời điểm làm demo này:

Thứ Hai, 12 tháng 11, 2012

Tìm thứ 2 và thứ 7 trong tuần của 1 ngày bất kỳ

Mình cần làm một công việc thống kê dữ liệu trong tuần từ thứ 2 đến thứ 7 nên cần tìm ra ngày thứ 2 và thứ 7 trong tuần của 1 ngày bất kỳ.

Ở đây mình không dám đặt tên hàm là First hay End Of Week vì vấn đề ngày Chủ Nhật có nơi coi là ngày đầu tuần, nhưng có nơi coi là ngày cuối tuần.

Trường hợp này mình xét ngày Chủ Nhật là ngày cuối tuần:
  1. public static DateTime MondayOfWeek(this DateTime date)  
  2. {  
  3.     var dayOfWeek = date.DayOfWeek;  
  4.   
  5.     if (dayOfWeek == DayOfWeek.Sunday)  
  6.     {  
  7.         //xét chủ nhật là đầu tuần thì thứ 2 là ngày kế tiếp nên sẽ tăng 1 ngày  
  8.         //return date.AddDays(1);  
  9.   
  10.         // nếu xét chủ nhật là ngày cuối tuần  
  11.         return date.AddDays(-6);  
  12.     }  
  13.   
  14.     // nếu không phải thứ 2 thì lùi ngày lại cho đến thứ 2  
  15.     int offset = dayOfWeek - DayOfWeek.Monday;  
  16.     return date.AddDays(-offset);  
  17. }  
  18.   
  19. public static DateTime SaturdayOfWeek(this DateTime date)  
  20. {  
  21.     return date.MondayOfWeek().AddDays(5);  
  22. }  

Thứ Tư, 7 tháng 11, 2012

Hàm bỏ dấu tiếng việt trong C#

Bỏ dấu bằng cách replace các ký tự có dấu về ký tự không dấu tương ứng:
  1. public static string RemoveUnicode(string text)  
  2. {  
  3.     string[] arr1 = new string[] { "á""à""ả""ã""ạ""â""ấ""ầ""ẩ""ẫ""ậ""ă""ắ""ằ""ẳ""ẵ""ặ",  
  4.     "đ",  
  5.     "é","è","ẻ","ẽ","ẹ","ê","ế","ề","ể","ễ","ệ",  
  6.     "í","ì","ỉ","ĩ","ị",  
  7.     "ó","ò","ỏ","õ","ọ","ô","ố","ồ","ổ","ỗ","ộ","ơ","ớ","ờ","ở","ỡ","ợ",  
  8.     "ú","ù","ủ","ũ","ụ","ư","ứ","ừ","ử","ữ","ự",  
  9.     "ý","ỳ","ỷ","ỹ","ỵ",};  
  10.     string[] arr2 = new string[] { "a""a""a""a""a""a""a""a""a""a""a""a""a""a""a""a""a",  
  11.     "d",  
  12.     "e","e","e","e","e","e","e","e","e","e","e",  
  13.     "i","i","i","i","i",  
  14.     "o","o","o","o","o","o","o","o","o","o","o","o","o","o","o","o","o",  
  15.     "u","u","u","u","u","u","u","u","u","u","u",  
  16.     "y","y","y","y","y",};  
  17.     for (int i = 0; i < arr1.Length; i++)  
  18.     {  
  19.         text = text.Replace(arr1[i], arr2[i]);  
  20.         text = text.Replace(arr1[i].ToUpper(), arr2[i].ToUpper());  
  21.     }  
  22.     return text;  
  23. }  
Viết theo kiểu Extension:
  1. public static string NonUnicode(this string text)  
  2. {  
  3.     string[] arr1 = new string[] { "á""à""ả""ã""ạ""â""ấ""ầ""ẩ""ẫ""ậ""ă""ắ""ằ""ẳ""ẵ""ặ",  
  4.     "đ",  
  5.     "é","è","ẻ","ẽ","ẹ","ê","ế","ề","ể","ễ","ệ",  
  6.     "í","ì","ỉ","ĩ","ị",  
  7.     "ó","ò","ỏ","õ","ọ","ô","ố","ồ","ổ","ỗ","ộ","ơ","ớ","ờ","ở","ỡ","ợ",  
  8.     "ú","ù","ủ","ũ","ụ","ư","ứ","ừ","ử","ữ","ự",  
  9.     "ý","ỳ","ỷ","ỹ","ỵ",};  
  10.     string[] arr2 = new string[] { "a""a""a""a""a""a""a""a""a""a""a""a""a""a""a""a""a",  
  11.     "d",  
  12.     "e","e","e","e","e","e","e","e","e","e","e",  
  13.     "i","i","i","i","i",  
  14.     "o","o","o","o","o","o","o","o","o","o","o","o","o","o","o","o","o",  
  15.     "u","u","u","u","u","u","u","u","u","u","u",  
  16.     "y","y","y","y","y",};  
  17.     for (int i = 0; i < arr1.Length; i++)  
  18.     {  
  19.         text = text.Replace(arr1[i], arr2[i]);  
  20.         text = text.Replace(arr1[i].ToUpper(), arr2[i].ToUpper());  
  21.     }  
  22.     return text;  
  23. }  
Test:
  1. string test1 = "hành trang lập trình chấm cơm".NonUnicode();  
  2. string test2 = Functions.RemoveUnicode("hành trang lập trình chấm cơm");  

Thứ Ba, 6 tháng 11, 2012

Cách làm hiệu ứng trượt khi mở Form C# Windows Form

Hôm nay ngồi coi lại cái tool viết hồi hơn 1 năm trước, tình cờ thấy lại đoạn code hồi xưa mình làm hiệu ứng trượt khi mở form con, sẵn tiện share cách làm cho ai có hứng thú.

Kéo vào Form con 1 Time Control sau đó khai báo các biến, hàm tạo và sự kiên Form Load như sau:
  1. private int _parentTop;  
  2. private int _parentLeft;  
  3. private int _parentWidth;  
  4. private int _parentHeight;  
  5.   
  6. public FrConnection(int parentTop, int parentLeft, int parentWidth, int parrentHeight)  
  7. {  
  8.     _parentTop = parentTop;  
  9.     _parentLeft = parentLeft;  
  10.     _parentWidth = parentWidth;  
  11.     _parentHeight = parrentHeight;  
  12.     InitializeComponent();  
  13. }  
  14.   
  15. private void FrConnection_Load(object sender, EventArgs e)  
  16. {  
  17.     Left = _parentLeft - 50;// vị trí khởi tạo của Form  
  18.     Top = ((_parentTop + _parentHeight / 2)) - (Height / 2);  
  19.     timer.Start();  
  20. }  
Ở sự kiện time_Tick khai báo:
  1. private void timer_Tick(object sender, EventArgs e)  
  2. {  
  3.     Left += 50;// tốc độ trượt của Form  
  4.     if (Left >= ((_parentLeft + _parentWidth / 2) - Width / 2))  
  5.     {  
  6.         Left = ((_parentLeft + _parentWidth / 2)) - (Width / 2);  
  7.         Top = ((_parentTop + _parentHeight / 2)) - (Height / 2);  
  8.         timer.Stop();  
  9.     }  
  10. }  
Ở Form cha, khi open Form con sẽ cần truyền các tham số top,left, width, heigh của mình vào Form con:
  1. private void newToolStripMenuItem_Click(object sender, EventArgs e)  
  2. {  
  3.     FrConnection fr = new FrConnection(this.Top, this.Left, this.Width, this.Height);  
  4.     fr.ShowDialog();  
  5. }  
Vị trí của Form con lúc bắt đầu khởi tạo:
 Sau đó Form sẽ trượt ra chính giữa:

Có thể tùy chỉnh quãng đường Form sẽ trượt tại sự kiện Form Load và tốc độ trượt của Form tại sự kiện time_Tick.

Thứ Hai, 5 tháng 11, 2012

Kiểm tra Hệ Điều Hành 64bit bằng C#

Để kiểm tra hệ điều hành đang chạy có phải 64bit hay không, xem thông tin trong class Enviroment.
  1. bool b = Environment.Is64BitOperatingSystem;

Nén và giải nén File trong C# .NET 4.5

Phiên bản .NET Framework 4.5 đã cung cấp thư viện hỗ trợ nén và giải nén file trong NameSpace System.IO.Compression mà các phiên bản .NET Framework trước đó chưa cung cấp.

Trước hết cần đảm bảo .NET 4.5 đã được cài đặt và add reference  System.IO.Compression.FileSystem

  1. //nén thư mục TestZipFile thành TestZipFile.zip  
  2. System.IO.Compression.ZipFile.CreateFromDirectory("C:\\Users\\Phong\\Desktop\\TestZipFile""C:\\Users\\Phong\\Desktop\\TestZipFile.zip");  
  3.   
  4. //giải nén TestZipFile.zip ra thư mục TestExtract  
  5. System.IO.Compression.ZipFile.ExtractToDirectory("C:\\Users\\Phong\\Desktop\\TestZipFile.zip""C:\\Users\\Phong\\Desktop\\TestExtract");  
Xem thêm các tính năng mới trong .NET 4.5 trên MSDN.

Thứ Sáu, 26 tháng 10, 2012

Nén và giải nén chuỗi trong C# (Compress and Decompress string C#)

Do nhu cầu công việc mình cần lưu trữ 1 nội dung rất lớn xuống database ( cụ thể là nội dung HTML của các website).
Với số lượng record lên đến hàng trăm ngàn, lượng dữ liệu lưu xuống là cực kỳ lớn, lên đến hàng chục GB. Dữ liệu thực sự của công ty là hàng triệu, có thể tưởng tưởng ra cái database để lưu trữ nó to đến mức nào ^^!.
Cho nên trước khi lưu xuống mình nén nội dung lại để giảm bớt dung lượng lưu trữ.
Cách làm này giúp tiết kiệm dung lượng lưu trữ rất lớn (Mình áp dụng test 100.000 record thì thấy database chỉ còn 1/3 so với khi chưa nén). Tuy nhiên khi cần ta không thể thực hiện các xử lý tính toán trực tiếp với dữ liệu này dưới SQL được mà cần phải lấy dữ liệu lên, giải nén ngược trở lại rồi xử lý.
  1. public static string Compress(string text)  
  2. {  
  3.     byte[] buffer = Encoding.UTF8.GetBytes(text);  
  4.     MemoryStream ms = new MemoryStream();  
  5.     using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))  
  6.     {  
  7.         zip.Write(buffer, 0, buffer.Length);  
  8.     }  
  9.   
  10.     ms.Position = 0;  
  11.     MemoryStream outStream = new MemoryStream();  
  12.   
  13.     byte[] compressed = new byte[ms.Length];  
  14.     ms.Read(compressed, 0, compressed.Length);  
  15.   
  16.     byte[] gzBuffer = new byte[compressed.Length + 4];  
  17.     System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);  
  18.     System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);  
  19.     return Convert.ToBase64String(gzBuffer);  
  20. }  
  1. public static string Decompress(string compressedText)  
  2. {  
  3.     byte[] gzBuffer = Convert.FromBase64String(compressedText);  
  4.     using (MemoryStream ms = new MemoryStream())  
  5.     {  
  6.         int msgLength = BitConverter.ToInt32(gzBuffer, 0);  
  7.         ms.Write(gzBuffer, 4, gzBuffer.Length - 4);  
  8.   
  9.         byte[] buffer = new byte[msgLength];  
  10.   
  11.         ms.Position = 0;  
  12.         using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))  
  13.         {  
  14.             zip.Read(buffer, 0, buffer.Length);  
  15.         }  
  16.   
  17.         return Encoding.UTF8.GetString(buffer);  
  18.     }  
  19. }  
Chú ý:
Đối với chuỗi dữ liệu lớn thì khi nén lại sẽ giảm kích thước rất nhiều. Trường hợp chuỗi ít hơn khoảng 300 hay 400 ký tự gì đấy (mình chưa test giới hạn) thì khi nén kết quả lại lớn hơn chuỗi ban đầu đấy (^^)!.

Thứ Hai, 22 tháng 10, 2012

Change Schema DB To DBO MS Sql Server

Lấy danh sách tất cả các table cần change Schema về dbo:
  1. SELECT 'ALTER SCHEMA dbo TRANSFER ' + SCHEMA_NAME(schema_id) + '.' + name  
  2. FROM sys.tables  
  3. WHERE schema_id != SCHEMA_ID('dbo'); 
Hoặc
  1. SELECT 'ALTER SCHEMA dbo TRANSFER ' + SCHEMA_NAME(schema_id) + '.' + name  
  2. FROM sys.objects  
  3. WHERE type='u' and schema_id != SCHEMA_ID('dbo');  
  4.       
Thực thi các câu truy vấn được tạo ra từ câu truy vấn trên.

Để change Schema cho Store Procedures thì làm tương tự (... from sys.procedures ...  hoặc ... from sys.objects where type='p' and ... ).

Xem thêm Xem danh sách các Object trong Database

Thứ Hai, 3 tháng 9, 2012

Một ví dụ mẫu đơn giản về cách sử dụng Linq to XML

  1.             XElement books = XElement.Parse(  
  2. @"<books>  
  3. <book>  
  4. <title>Pro LINQ: Language Integrated Query in C# 2010</title>  
  5. <author>Joe Rattz</author>  
  6. </book>  
  7. <book>  
  8. <title>Pro .NET 4.0 Parallel Programming in C#</title>  
  9. <author>Adam Freeman</author>  
  10. </book>  
  11. <book>  
  12. <title>Pro VB 2010 and the .NET 4.0 Platform</title>  
  13. <author>Andrew Troelsen</author>  
  14. </book>  
  15. </books>");  
  16.             var titles =  
  17.             from book in books.Elements("book")  
  18.             where (string)book.Element("author") == "Joe Rattz"  
  19.             select book.Element("title");  
  20.             foreach (var title in titles)  
  21.                 Console.WriteLine(title.Value);  
  22.             Console.ReadLine();  
  23.       

Thứ Sáu, 31 tháng 8, 2012

Tắt chức năng postback của button control ASP.NET

Set OnClientClick="return false;". Nếu có hàm cần làm việc trên client thì đặt return false ngay sau các hàm trên client. Ví dụ set OnClientClick="hamCuaBan();return false;". Khi click vào button sẽ thực thi hàm hamCuaBan() và sau đó  gặp đoạn return false; nó sẽ không postback lên server nữa.
  1. <asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="return false;" />  
Để hiểu rõ quá trình làm việc của button control ta set UseSubmitBehavior="false" và đăng ký sự kiện onclick="Button1_Click":
  1. <asp:Button ID="Button1" UseSubmitBehavior="false" runat="server" Text="Button" OnClientClick="return false;" onclick="Button1_Click" />  
Khi control render, view page source sẽ thấy:
  1. <input type="button" id="Button1" onclick="return false;__doPostBack('Button1','')" value="Button" name="Button1">  
  2.       
UseSubmitBehavior="false" thì type="button" thay vì type="submit". Khi type="button" thì khi click vào nó sẽ không tự động postback mà phải viết hàm cho nó để có thể postback lên server.

Để ý đoạn
  1. onclick="return false;__doPostBack('Button1','')"    
.ASP.NET nó tự thêm hàm để postback lên server đặt sau các hàm xử lý bên client.
__doPostBack('Button1','') chính là hàm để postback lên xử lý để xử lý các sự kiện trên server . Trường hợp này nó sẽ thực thi sự kiện onclick="Button1_Click". Nếu không đăng ký sự kiện trên server cho button nó sẽ không phải làm gì cả tuy nhiên nó vẫn postback lên server.

Quá trình xử lý khi click vào button:  nó sẽ thực hiện các hàm bên phía client trước sau đó sẽ thực hiện tiếp các hàm postback. Nếu ta chèn thêm 1 đoạn return false vào sự kiện ở client thì tất cả các hàm phía sau nó sẽ không thực hiện nữa, do đó sẽ không postback lên server nữa. Vì các hàm postback bị đặt sau các hàm bên client nếu có.

Để chứng mình điều này ta làm thử 1 ví dụ:

Set lại hàm:
  1. OnClientClick="alert('trước return');return false;alert('sau return')"    
Khi render sẽ thấy:
  1. onclick="alert('trước return');return false;alert('sau return');__doPostBack('Button1','')"     
Click vào button sẽ chỉ hiện thị alert box "trước return" và không làm gì phía sau return false nữa cả. Nếu bỏ đoạn return false; đi nó sẽ hiển thị lần lượt 2 alert box và trang sẽ bị load lại do postback.

Thứ Hai, 20 tháng 8, 2012

Con trỏ hàm trong C#

Khái niệm con trỏ hàm mình không giải thích ở đây. Ai sử dụng delegate để viết các sự kiện cho các control thì chắc đã rành về cái này.

Đi thẳng vào ví dụ luôn:

Giả sử ta có các hàm làm phép tính như sau:
  1. public static int Cong(int n1, int n2)  
  2. {  
  3.     return n1 + n2;  
  4. }  
  5.   
  6. public static int Tru(int n1, int n2)  
  7. {  
  8.     return n1 - n2;  
  9. }  
  10.   
  11. public static int Nhan(int n1, int n2)  
  12. {  
  13.     return n1 * n2;  
  14. }  
  15.   
  16. public static int Chia(int n1, int n2)  
  17. {  
  18.     return n1 / n2;  
  19. }  
Bây giờ ta viết 1 hàm làm phép tính bất kỳ cho người dùng. Hàm này sẽ không làm gì cả mà nó sẽ ủy quyền (delegate) cho hàm tương ứng mà người dùng muốn sử dụng:
  1. public static int Tinh(int n1, Func<intintint> tenHamTinh, int n2)  
  2. {  
  3.     return tenHamTinh(n1, n2);  
  4. }  
Chú ý tham số tenHamTinh là ta truyền hàm muốn tính vào: Func<intintint> tenHamTinh. Trong <intintint> thì int cuối cùng là kiểu dữ liệu trả về của hàm, các int phía trước lần lượt là các kiểu dữ liệu của các tham số của hàm truyền vào. Khi ta truyền hàm muốn tính vào thì hàm muốn tính phải thỏa các điều kiện đó ( ở đây hàm truyền vào phải có 2 tham số  kiểu int và kết quả trả về là kiểu int).

Để sử dụng thì làm như sau:
  1. int tong = Tinh(10, Cong, 20);  
  2.   
  3. int hieu = Tinh(10, Tru, 30);  
Demo:
  1. Console.WriteLine("10 + 20 =" + Tinh(10, Cong, 20));  
  2. Console.WriteLine("10 - 20 =" + Tinh(10, Tru, 20));  

Thứ Tư, 15 tháng 8, 2012

Timeout khi thay đổi cấu trúc của table trong SQL

Khi chỉnh sửa các column trong table hoặc thêm column mới vào giữa table. SQL sẽ lưu dữ liệu hiện tại của table qua 1 bảng tạm, sau đó xóa table cũ và đổi tên table tạm lại thành table cũ ...

Quá trình này nếu thực hiện trên table có dữ liệu lớn sẽ mất khá nhiều thời gian. Nếu save ở chế độ Design sẽ bị tình trạng timeout.

Cách giải quyết là generate script và thực thi script này.

Nhìn vào script được generate ra cũng sẽ giúp hiểu được quá trình làm việc của SQL khi sửa table.

Thứ Hai, 13 tháng 8, 2012

Cancel các tiến trình khi làm việc đa tiến trình sử dụng ParallelOptions

Khai báo 1 CancellationTokenSource, set CancellationTokenSource.Token cho CancellationToken của ParallelOptions.

Ví dụ: 
  1. CancellationTokenSource cts = new CancellationTokenSource();   
  2. ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 10, CancellationToken = cts.Token };   
Khi muốn hủy quá trình làm việc thì gọi:
  1. cts.Cancel();   

Thứ Sáu, 10 tháng 8, 2012

Xem địa chỉ IP của client kết nối tới MS SQL Server

Xem danh sách các địa chỉ IP kết nối tới SQL Server là việc cần thiết, nó cho ta biết các địa chỉ IP nào đang kết nối tới SQL Server.

Ứng dụng của bạn chỉ chạy từ 1 địa chỉ IP và bạn chỉ đăng nhập vào SQL Server từ 1 địa chỉ IP duy nhất. Tuy nhiên bạn phát hiện ra trong danh sách có nhiều IP lạ đang đăng nhập vào SQL Server, các địa chỉ IP này không nằm trong danh sách IP bạn đã sử dụng. Lúc này bạn cần phải kiểm tra gấp lại mật khẩu rồi đấy.

Để xem thông tin chi tiết các connections đang kết nối tới SQL Server:
  1. select * from sys.dm_exec_connections     
Lấy địa chỉ IP:
  1. select client_net_address from sys.dm_exec_connections
Có thể viết 1 ứng dụng nhỏ sử dụng thông tin trên để thường xuyên kiểm tra nếu phát hiện IP lạ thì sẽ báo động cho người quản trị server.

Thứ Năm, 9 tháng 8, 2012

Xem số lượng connections đang kết nối tới MS SQL Server

Group theo từng database:
  1. SELECT   
  2.     DB_NAME(dbid) as DBName,   
  3.     COUNT(dbid) as NumberOfConnections,  
  4.     loginame as LoginName  
  5. FROM  
  6.     sys.sysprocesses  
  7. WHERE   
  8.     dbid > 0  
  9. GROUP BY   
  10.     dbid, loginame  
  11.       
Lấy tổng số:
  1. SELECT   
  2.     COUNT(dbid) as TotalConnections  
  3. FROM  
  4.     sys.sysprocesses  
  5. WHERE   
  6.     dbid > 0  
  7.       
Xem chi tiết:
  1. sp_who2 'Active'  
  2.       
Nguồn: http://stackoverflow.com

Thứ Tư, 8 tháng 8, 2012

Cách sử dụng ( đọc, thêm, sửa, xóa ) appSettings trong file web.config C# ASP.NET

Các thao tác đọc, thêm, sửa, xóa appSettings tương tự như các thao tác với app.config. Tuy nhiên có sự khác nhau về cách đọc file config.

Xem thao tác với app.config C#

Ví dụ hàm sửa appSettings:
  1. public static void EditAppSetting(string key, string value)  
  2. {  
  3.     System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/");  
  4.     config.AppSettings.Settings[key].Value = value;  
  5.     config.Save(ConfigurationSaveMode.Modified);  
  6.     ConfigurationManager.RefreshSection("appSettings");  
  7. }  
Tham số truyền vào hàm OpenWebConfiguration là đường dẫn thư mục file web.config cần load. Nếu bằng null thì mặc định là file web.config ở thư mục cao nhất.

Note: Nếu gặp lỗi Failed to map the path thì xem Khắc phục lỗi 'Failed to map the path' khi load file web.config

Thứ Tư, 1 tháng 8, 2012

Ngắt khoảng cách cho số bằng cách sử dụng phương thức ToString(string format)

Một cách nhanh để ngắt khoảng cách cho các chuỗi số là ta convert chúng về số sau đó sử dụng phương thức .ToString(string format)
  1. int number = int.MaxValue;  
  2. string format = number.ToString("###,###");  

Thứ Ba, 31 tháng 7, 2012

Sử dụng LINQ để truy vấn dữ liệu trong 1 DataTable

Trước hết phải add reference System.Data.DataSetExtensions.dll để sử dụng phương thức extension AsEnumerable() cho DataTable.

Demo:
  1. // tạo 1 datatable để test  
  2. DataTable table = new DataTable("table");  
  3. table.Columns.Add(new DataColumn("Name"typeof(string)));  
  4. table.Columns.Add(new DataColumn("Age"typeof(int)));  
  5. for (int i = 0; i < 5; i++)  
  6. {  
  7.     DataRow NewRow = table.NewRow();  
  8.     NewRow["Name"] = "Nguyễn Văn " + i;  
  9.     NewRow["Age"] = i;  
  10.     table.Rows.Add(NewRow);  
  11. }  
  12.   
  13. // lấy danh sách những người có tuổi >= 3  
  14. var query = from row in table.AsEnumerable() where row.Field<int>("Age") >=3 select row;  
  15. DataTable dt = query.CopyToDataTable();  
DataTable gốc:


DataTable từ câu truy vấn:


Thứ Hai, 30 tháng 7, 2012

Cấu hình thông báo lỗi 404 not found cho website trong web.config

Thông báo lỗi 404 not found khi người dùng truy cập vào 1 đường dẫn không tồn tại trong website. Việc cài đặt cấu hình sẽ giúp chuyển hướng người dùng đến trang thông báo hoặc chuyển về trang mặc định nào đó khi xảy ra lỗi thay vì hiển thị thông điệp khó hiểu của hệ thống.

Cấu hình trong <system.web>    </system.web>:
  1. <customErrors mode="On" defaultRedirect="~/trang-chu.aspx">  
  2.   <error statusCode="404" redirect="~/thong-bao.aspx"/>  
  3. </customErrors>  
Trong trường hợp đường dẫn không tồn tại (statusCode = 404) trình duyệt sẽ được chuyển tới trang thong-bao.aspx để thông báo hoặc hướng dẫn cho người dùng.

Các trường hợp lỗi khác (statusCode khác) nếu xảy ra nhưng không được cấu hình riêng thì được chuyển về trang mặc định defaultRedirect.

Danh sách mã lỗi( statusCode ) có thể xem tại http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Note:
Cấu hình thông báo lỗi có thể gây khó khăn cho việc test trong quá trình xây dựng website.
Có 3 mode là On, Off và RemoteOnly. Để test thử cấu hình của bạn thì để mode là On, sau đó nên để mode là RemoteOnly, lúc này khi chạy ứng dụng ở local bạn vẫn  sẽ nhận được thông báo lỗi của hệ thống nếu có lỗi xảy ra.

Chủ Nhật, 29 tháng 7, 2012

Restore database vào một vị trí mới và đặt lại tên cho database

Đôi khi ta chuyển database từ server cũ qua server mới. Khi tạo lại database bằng cách restore từ 1 bản backup thường báo lỗi không tìm thấy thư mục chứa database. Lúc này ta phải tạo sẵn một thư mục có đường dẫn giống với đường dẫn của thư mục chứa database bên server cũ.
Nếu ta muốn đặt database ở một thư mục khác thì thay vì sử dụng câu lệnh restore thông thường, sử dụng đoạn lệnh mẫu sau để chỉ định thư mục chứa database sau khi restore:
  1. USE master  
  2. GO  
  3. -- First determine the number and names of the files in the backup.  
  4. -- AdventureWorks2008R2_Backup is the name of the backup device.  
  5. RESTORE FILELISTONLY  
  6.    FROM AdventureWorks2008R2_Backup  
  7. -- Restore the files for MyAdvWorks.  
  8. RESTORE DATABASE MyAdvWorks -- có thể đổi tên mới ở chỗ này  
  9.    FROM AdventureWorks2008R2_Backup  
  10.    WITH RECOVERY,  
  11.    MOVE 'AdventureWorks2008R2_Data' TO 'D:\MyData\MyAdvWorks_Data.mdf',   
  12.    MOVE 'AdventureWorks2008R2_Log' TO 'F:\MyLog\MyAdvWorks_Log.ldf'  
  13. GO  
  14.       
Xem hướng dẫn chi tiết trên MSDN

Sử dụng Clipboard bằng javascript

Để đưa 1 giá trị text vào clipboard:
  1. window.clipboardData.setData('Text','aaaaaaaa');  
  2.       
Để lấy giá trị text đang lưu trong clipboard:
  1. var value = window.clipboardData.getData("Text");  
  2.       
Tuy nhiên để các hàm này hoạt động thì trình duyệt người dùng phải cho phép sử dụng clipboard. Hiện giờ đa số các trình duyệt đã disable tính năng này vì lý do an ninh hay 1 vài vấn đề khác:

Problems caused by unintended clipboard access

There are several types of problems which can happen if a website is able to use your system's clipboard through javascript:
  • A website may erase the clipboard data, which may cause you to lose important data that you had copied previously into the clipboard.
  • A website may change the clipboard data, which may cause different data to be pasted later on instead of the data you intended to paste originally.
  • A website may read the clipboard data, and use them in malicious ways or send them to a third party without your knowledge.
Therefore, you should only permit the websites that you absolutely trust to be able to access the clipboard.

Thứ Bảy, 28 tháng 7, 2012

Sử dụng Clipboard trong .NET

.NET cung cấp class Clipboard gồm các phương thức tĩnh để thao tác với Clipboard.

Ví dụ: Để đưa 1 đoạn text vào clipboard sử dụng:
  1. Clipboard.SetText("hanhtranglaptrinh.com");  
Kiểm tra bằng cách kiếm cái ô text nào đó Ctrl + V hoặc click phải chuột chọn paste sẽ thấy kết quả.

Để lấy 1 đoạn text đang được lưu trong clipboard ra sử dụng:
  1. string text = Clipboard.GetText();  
Kiểm tra bằng cách kiếm 1 đoạn văn bản nào đó bôi đen -> chuột phải chọn copy hoặc Ctrl + C sau đó chạy đoạn code trên và kiếm tra biến text.

Đối với ứng dụng windows (windows form, WPF, ... ) thì ngoài text ra còn có thể đưa một số object khác (Image, Stream, ...)  vào Clipboard. Ứng dụng silverlight chỉ hỗ trợ text.

Gửi Email bằng MS SQL Server

Sử dụng đoạn script sau để gửi email trong SQL Server:
  1. EXEC msdb.dbo.sp_send_dbmail  
  2. @profile_name ='Tên của cấu hình đã cài đặt để gửi mail',  
  3. @recipients=N'email người nhận',  
  4. @body=N'Nội dung email',  
  5. @subject = 'subject',  
  6. @body_format = 'HTML'  
  7.       
Note: Trước khi gửi email bạn phải cấu hình email trong SQL Server thì mới có thể gửi được email.

Thứ Sáu, 27 tháng 7, 2012

Dấu hỏi ? ngay sau kiểu dữ liệu có ý nghĩa gì trong C#

Đối với các kiểu dữ liệu không có giá trị null.
Ví dụ kiểu bool thì chỉ có 2 giá trị là true và false, kiểu int thì là những con số, ...
Khi bạn khai báo như sau sẽ bị báo lỗi:
  1. int a = null;  
  2. bool b = null;  
Hoặc:
  1. public int GetNull()  
  2. {  
  3.     return null;  
  4. }  
Hoặc khai báo hàm như sau:
  1. public static void XuLy(int a, int b)  
  2. { }  
Nhưng lúc truyền biến vào hàm là giá trị null:
  1. XuLy(1, null);  
Sử dụng dấu hỏi ? ngay sau kiểu dữ liệu ta được 1 kiểu dữ liệu mới. Miền giá trị bao gồm miền giá trị của kiểu dữ liệu cũ và thêm giá trị null nữa.
Khai báo như sau sẽ không còn báo lỗi nữa:
  1. int? a = null;  
  2. bool? b = null;  
  1. public int? GetNull()  
  2. {  
  3.     return null;  
  4. }  
  1. public static void XuLy(int a, int? b)  
  2. { }  
Note:
 - Chỉ có thể gán kiểu dữ liệu not null cho kiểu dữ liệu có thể null chứ ngược lại thì không.
 - Ví dụ có thể gán:
  1. int a = 5;  
  2. int? b = a;  
Chứ không thể gán:
  1. int? a = 5;  
  2. int b = a;  
Hoặc không thể:
  1. public int Test()  
  2. {  
  3.     return GetNull();  
  4. }  
  5. public int? GetNull()  
  6. {  
  7.     return null;  
  8. }  

Lấy thông tin các column và table từ INFORMATION_SCHEMA trong database Sql Server

Ngoài việc lấy thông tin các column và table từ sys.objects ta còn có thể xem thông tin các column và table trong INFORMATION_SCHEMA.

Xem thông tin các column trong database:
  1. select * from INFORMATION_SCHEMA.COLUMNS  
  2.       
Xem danh sách các table:
  1. select * from INFORMATION_SCHEMA.TABLES 
  2.       
Kết quả trả về bao gồm cả danh sách các View nữa. Nếu chỉ muốn lấy danh sách Table thôi thì filter theo TABLE_TYPE
  1. select * from INFORMATION_SCHEMA.TABLES where TABLE_TYPE ='BASE TABLE'  
  2.       
Ví dụ trong database mình có 1 table là tblBug.
Muốn xem danh sách các column của  tblBug:
  1. select TABLE_NAME, COLUMN_NAME, DATA_TYPE from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='tblBug'  
  2.       

Hoặc tìm xem tất cả các Table nào có chứa column tên là DomainID:
  1. select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='DomainID'  
  2.       
Vậy là có thêm một cách nữa để xem nhanh danh sách các column và table trong database rồi. Sử dụng thông tin này để generate source code tự động nữa thì cũng tuyệt ^^!.

Thứ Năm, 26 tháng 7, 2012

Cách sử dụng ( đọc, thêm, sửa, xóa ) appSettings trong file app.config C#

Hiện giờ thường chỉ những file cấu hình đặc biệt người ta mới sử dụng file xml để cấu hình cho ứng dụng. Với những cấu hình không quá phức tạp thì việc sử dụng appSettings trong file app.config cực kỳ nhanh gọn.

Khai báo biến 'abc' có giá trị '01/01/1900 00:00:00 AM' trong appSettings  trong file app.config:
  1. <?xml version="1.0"?>  
  2. <configuration>  
  3. <startup>  
  4.   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>  
  5.   <appSettings>  
  6.     <add key="abc" value="01/01/1900 00:00:00 AM"/>  
  7.   </appSettings>  
  8. </configuration>  
  9.       
Để đọc giá trị của abc sử dụng:
  1. string abc = ConfigurationManager.AppSettings["abc"];  
  2.       
Khi cần thay đổi các giá trị cấu hình này, cách đơn giản nhất là mở file config lên và sửa ^^!. Tuy nhiên đối với những ứng dụng cho người dùng cuối, không thể bắt người dùng tự vào chỉnh sửa được mà ta phải làm chức năng cho họ cấu hình. Dưới đây là một số hàm cần thiết để chỉnh sửa file config.

- Sửa giá trị của biến trong appSettings trong file app.config:
  1. public static void EditAppSetting(string key, string value)  
  2. {  
  3.     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);  
  4.     config.AppSettings.Settings[key].Value = value;  
  5.     config.Save(ConfigurationSaveMode.Modified);  
  6.     ConfigurationManager.RefreshSection("appSettings");  
  7. }  
- Thêm 1 giá trị mới vào appSettings trong file app.config:
  1. public static void AddAppSetting(string key, string value)  
  2. {  
  3.     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);  
  4.     config.AppSettings.Settings.Add(key,value);  
  5.     config.Save(ConfigurationSaveMode.Modified);  
  6.     ConfigurationManager.RefreshSection("appSettings");  
  7. }  
- Xóa 1 giá trị ra khỏi appSettings trong file app.config:
  1. public static void RemoveAppSetting(string key)  
  2. {  
  3.     System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);  
  4.     config.AppSettings.Settings.Remove(key);  
  5.     config.Save(ConfigurationSaveMode.Modified);  
  6.     ConfigurationManager.RefreshSection("appSettings");  
  7. }  
Demo thử hàm edit nào:
  1. Console.WriteLine(ConfigurationManager.AppSettings["abc"]);  
  2. EditAppSetting("abc",DateTime.Now.ToString());  
  3. Console.WriteLine(ConfigurationManager.AppSettings["abc"]);  
  4. Console.ReadLine();  
Dòng đầu tiên sẽ in ra giá trị của abc trước khi sửa file config.
Dòng thứ 2 tiến hành sửa giá trị abc thành giá trị thời gian hiện tại trong file config.
Dòng thứ 3 tiến hành đọc lại và in ra giá trị của abc sau khi đã sửa file config.
Chạy lại thêm một lần nữa :
Vậy là xong. Sử dụng app.config nhanh hơn so với thao tác đọc và ghi file xml nhiều đúng không nào.

Note:
- Cần add Reference System.configuration.
- Sau khi chạy chương trình thì file config bị chỉnh sửa là file config trong cùng thư mục chứa file exe (có dạng TenUngDung.exe.config) chứ không phải file app.config trong project đâu nhé.
- Quá trình sửa file config chỉ chính xác khi build ứng dụng ra thành file exe và chạy. Nếu chạy trong chế độ debug thì bị tình trạng là đọc từ file TenUngDung.exe.config nhưng lại ghi ra file TenUngDung.vshost.exe.config.

Thứ Tư, 25 tháng 7, 2012

Sử dụng DataView để filter dữ liệu từ DataTable C#

Khi chúng ta được cung cấp 1 DataTable chứa dữ liệu nhưng chỉ cần lấy ra 1 số dòng thỏa điều kiện nào đó thôi. Cách truyền thống vấn là duyệt từng dòng rồi so sánh giá trị nếu phù hợp thì lấy, không phù hợp thì bỏ qua.
Sử dụng DataView để lấy dữ liệu theo điều kiện nào đó 1 cách nhanh chóng.

Demo:
Tạo 1 DataTable chứa thông tin tên và tuổi của một số người:
  1. DataTable table = new DataTable("table");  
  2. table.Columns.Add(new DataColumn("Name"typeof(string)));  
  3. table.Columns.Add(new DataColumn("Age"typeof(int)));  
  4. for (int i = 0; i < 5; i++)  
  5. {  
  6.     DataRow NewRow = table.NewRow();  
  7.     NewRow["Name"] = "Nguyễn Văn " + i;  
  8.     NewRow["Age"] = i;  
  9.     table.Rows.Add(NewRow);  
  10. }  
Bây giờ nếu chỉ muốn lấy những người có tuổi lớn hơn 2:
  1. // new 1 DataView  
  2. DataView dataView = new DataView(table);  
  3.   
  4. // chỉ lấy những người có tuổi lớn hơn 2  
  5. dataView.RowFilter = "Age > 2";  
Vậy là Ok, lúc này DataView chỉ chứa những dòng có giá trị thỏa điều kiện filter. Có thể dùng DataView này để đưa vào DataGridView.

Sử dụng 2 hàm sau để test kết quả:
  1. private static void PrintTable(DataTable table)  
  2. {  
  3.     for (int i = 0; i < table.Rows.Count; i++)  
  4.     {  
  5.         Console.WriteLine("\t" + table.Rows[i]["Name"] +": "+ table.Rows[i]["Age"] + " tuổi.");  
  6.     }  
  7.     Console.WriteLine();  
  8. }  
  9.   
  10. private static void PrintView(DataView view)  
  11. {  
  12.     for (int i = 0; i < view.Count; i++)  
  13.     {  
  14.         Console.WriteLine("\t" + view[i]["Name"] + ": " + view[i]["Age"] + " tuổi.");  
  15.     }  
  16.     Console.WriteLine();  
  17. }  
Thực hiện test:
  1. DataTable table = new DataTable("table");  
  2. table.Columns.Add(new DataColumn("Name"typeof(string)));  
  3. table.Columns.Add(new DataColumn("Age"typeof(int)));  
  4. for (int i = 0; i < 5; i++)  
  5. {  
  6.     DataRow NewRow = table.NewRow();  
  7.     NewRow["Name"] = "Nguyễn Văn " + i;  
  8.     NewRow["Age"] = i;  
  9.     table.Rows.Add(NewRow);  
  10. }  
  11.   
  12. // new 1 DataView  
  13. DataView dataView = new DataView(table);  
  14.   
  15. // chỉ lấy những người có tuổi lớn hơn 2  
  16. dataView.RowFilter = "Age > 2";  
  17.   
  18. PrintTable(table);  
  19. PrintView(dataView);  
  20. Console.ReadLine();  
Kết quả sau khi filter chỉ còn Nguyễn Văn 3 và Nguyễn Văn 4: