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();